Java: Quản lý siêu dữ liệu (File và File lưu các thuộc tính)

Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực

Siêu dữ liệu là "dữ liệu về dữ liệu khác". Với một hệ thống tập tin, dữ liệu được chứa trong các tập tin và thư mục của nó, và siêu dữ liệu theo dõi thông tin về từng đối tượng: Nó là một tập tin chính quy, một thư mục, hay một liên kết? Kích thước của nó, ngày tạo, ngày sửa đổi cuối cùng, chủ sở hữu tập tin, nhóm chủ sở hữu và các quyền hạn truy cập là gì?

Siêu dữ liệu của hệ thống tập tin được thường được tham chiếu như là các thuộc tính tập tin. Lớp Files bao gồm các phương thức có thể được sử dụng để có được một thuộc tính duy nhất của một tập tin, hoặc để thiết lập một thuộc tính.

Phương thức Chú thích
size(Path) Trả về kích thước của tập tin chỉ định trong byte.
isDirectory(Path, LinkOption) Trả về true nếu Path được chỉ định định vị một tập tin đó là một thư mục.
isRegularFile(Path, LinkOption...) Trả về true nếu Path được chỉ định định vị tập tin đó là một tập tin chính quy.
isSymbolicLink(Path) Trả về true nếu Path được chỉ định định vị tập tin đó là một liên kết tượng trưng.
isHidden(Path) Trả về true nếu Path được chỉ định định vị tập tin được xét là ẩn bởi hệ thống tập tin.
getLastModifiedTime(Path, LinkOption...)
setLastModifiedTime(Path, FILETIME)
Trả về hoặc thiết lập thời gian sửa đổi cuối cùng của tập tin được chỉ định.
getOwner(Path, LinkOption...) 
setOwner(Path, UserPrincipal)
Trả về hoặc thiết lập chủ sở hữu của các tập tin.
getPosixFilePermissions(Path, LinkOption...) 
setPosixFilePermissions(Path, Set <PosixFilePermission>)
Trả về hoặc thiết lập quyền truy cập file POSIX của một tập tin.
getAttribute(Path, String, LinkOption...) 
setAttribute(Path, String, Object, LinkOption...)
Trả về hoặt thiết lập giá trị của một thuộc tính tập tin.

Nếu một chương trình cần nhiều thuộc tính tập tin trong cùng khoảng thời gian, thì có thể sẽ không hiệu quả nếu sử dụng các phương thức lấy một thuộc tính đơn. Liên tiếp truy cập vào hệ thống tập tin để lấy một thuộc tính duy nhất có thể ảnh hưởng xấu đến hiệu suất. Vì lý do này, lớp cung cấp hai phương thức readAttributes để lấy các thuộc tính của một tập tin trong một hoạt động với số lượng lớn.

Phương thức Chú thích
readAttributes(Path, String, LinkOption...) Đọc các thuộc tính của một tập tin như là một hoạt động thu thập. Tham số String xác định các thuộc tính được đọc.
readAttributes(Path, Class <A>, LinkOption...) Đọc các thuộc tính của một tập tin như là một hoạt động thập. Tham số Class <A> là các loại thuộc tính được yêu cầu và phương thức trả về một đối tượng của lớp đó.

Trước khi xem ví dụ về các phương thức readAttributes, ta cần biết rằng các hệ thống tập tin khác nhau có những quan niệm khác nhau về những thuộc tính cần được theo dõi. Vì lý do này, các thuộc tính tập tin có liên quan được nhóm lại với nhau thành các view. Một view ánh xạ tới một sự thực thi hệ thống tập tin cụ thể, chẳng hạn như POSIX hay DOS, hoặc đến một chức năng phổ biến, chẳng hạn như quyền sở hữu tập tin.

Dưới đây là các view được hỗ trợ:

  • BasicFileAttributeView - Cung cấp một view cho các thuộc tính cơ bản được yêu cầu để được hỗ trợ bởi tất cả các triển khai hệ thống tập tin.

  • DosFileAttributeView - Mở rộng view thuộc tính cơ bản với bốn bit chuẩn được hỗ trợ trên các hệ thống tập tin có hỗ trợ các thuộc tính hệ điều hành DOS.

  • PosixFileAttributeView - Mở rộng view thuộc tính cơ bản với các thuộc tính hỗ trợ trên hệ thống tập tin hỗ trợ các chuẩn POSIX, chẳng hạn như UNIX. Những thuộc tính này bao gồm chủ sở hữu tập tin, nhóm chủ sở hữu, và chín quyền truy cập có liên quan.

  • FileOwnerAttributeView - Được hỗ trợ bởi bất kỳ sự thực thi hệ thống tập tin nào có hỗ trợ các ý niệm về chủ sở hữu tập tin.

  • AclFileAttributeView - Hỗ trợ đọc hoặc cập nhật danh sách điều khiển truy cập của tập tin (Access Control Lists - ACL). Mô hình ACL NFSv4 cũng được hỗ trợ. Bất kỳ mô hình ACL nào, chẳng hạn như mô hình ACL Windows, mà có một ánh xạ rõ ràng sao cho các mô hình NFSv4 cũng có thể được hỗ trợ.

  • UserDefinedFileAttributeView - Cho phép hỗ trợ siêu dữ liệu mà là người dùng định nghĩa. View này có thể được ánh xạ tới bất kỳ cơ chế mở rộng một hệ thống hỗ trợ nào. Trong hệ điều hành Solaris, bạn có thể sử dụng chế độ này để lưu trữ các kiểu MIME của một tập tin.

Một sự thực thi hệ thống tập tin cụ thể chỉ có thể hỗ trợ loại view tập tin thuộc tính cơ bản, hoặc nó có thể hỗ trợ một số view thuộc tính tập tin này. Một view hệ thống tập tin có thể hỗ trợ các view thuộc tính khác không nằm trong API này.

Trong hầu hết các trường hợp, bạn không cần phải đối phó trực tiếp với bất kỳ một giao diện FileAttributeView nào. Nếu bạn cần phải làm việc trực tiếp với FileAttributeView, bạn có thể truy cập thông qua phương thức getFileAttributeView(Path, Class <V>, LinkOption...).

Phương thức readAttributes sử dụng các generic và có thể được sử dụng để đọc các thuộc tính cho bất kỳ view thuộc tính tập tin nào. Các ví dụ trong phần còn lại của bài viết này sử dụng phương thức readAttributes.

Phần tiếp theo của bài viết bao gồm các chủ đề sau:

  • Các thuộc tính tập tin cơ bản
  • Thiết lập dấu thời gian
  • Thuộc tính tập tin DOS
  • Phân quyền tập tin POSIX
  • Thiết lập một tập tin hoặc chủ sở hữu nhóm
  • Thuộc tính tập tin người dùng định nghĩa
  • Thuộc tính lưu trữ tập tin

Các thuộc tính tập tin cơ bản

Như đã đề cập ở trên, để đọc các thuộc tính cơ bản của một tập tin, ta có thể sử dụng một trong những phương thức Files.readAttributes, đọc tất cả các thuộc tính cơ bản trong một hoạt động hợp nhất. Điều này hiệu quả hơn nhiều so với truy cập vào từng hệ thống tập tin riêng biệt để đọc từng thuộc tính riêng. Đối số varargs hiện tại hỗ trợ kiểu liệt kê LinkOptionNOFOLLOW_LINKS. Sử dụng tùy chọn này khi ta muốn bỏ qua liên kết tượng trưng.


Đôi lời về dấu thời gian:  Tập hợp các thuộc tính cơ bản bao gồm ba dấu thời gian: creationTimelastModifiedTime, và lastAccessTime. Bất kỳ dấu thời gian nào cũng có thể không được hỗ trợ trong việc thực thi cụ thể, trong đó có trường hợp các phương thức truy xuất tương ứng trả về một giá trị thực thi cụ thể. Khi được hỗ trợ, dấu thời gian sẽ được trả về như một đối tượng FILETIME.

Đoạn mã dưới đây đọc và in các thuộc tính tập tin cơ bản cho tập tin đã cho và sử dụng các phương thức của lớp BasicFileAttributes.

Path file = ...;
BasicFileAttributes attr = Files.readAttributes(file, BasicFileAttributes.class);

System.out.println("creationTime: " + attr.creationTime());
System.out.println("lastAccessTime: " + attr.lastAccessTime());
System.out.println("lastModifiedTime: " + attr.lastModifiedTime());

System.out.println("isDirectory: " + attr.isDirectory());
System.out.println("isOther: " + attr.isOther());
System.out.println("isRegularFile: " + attr.isRegularFile());
System.out.println("isSymbolicLink: " + attr.isSymbolicLink());
System.out.println("size: " + attr.size());

 

Ngoài các phương thức accessor thể hiện trong ví dụ trên, có một phương thức có tên fileKey trả về hoặc là một đối tượng xác định duy nhất các tập tin hoặc là rỗng nếu không có sẵn khóa (key) cho tập tin.

Thiết lập dấu thời gian

Đoạn mã sau thiết lập thời gian sửa đổi lần cuối theo đơn vị mini giây:

Path file = ...;
BasicFileAttributes attr =
    Files.readAttributes(file, BasicFileAttributes.class);
long currentTime = System.currentTimeMillis();
FileTime ft = FileTime.fromMillis(currentTime);
Files.setLastModifiedTime(file, ft);
}

 

Thuộc tính tập tin DOS

Các thuộc tính tập tin DOS cũng được hỗ trợ trên hệ thống tập tin khác với DOS, như Samba chẳng hạn. Đoạn mã sau đây sử dụng các phương thức của lớp DosFileAttributes.

Path file = ...;
try {
    DosFileAttributes attr =
        Files.readAttributes(file, DosFileAttributes.class);
    System.out.println("isReadOnly is " + attr.isReadOnly());
    System.out.println("isHidden is " + attr.isHidden());
    System.out.println("isArchive is " + attr.isArchive());
    System.out.println("isSystem is " + attr.isSystem());
} catch (UnsupportedOperationException x) {
    System.err.println("DOS file" +
        " attributes not supported:" + x);
}

Tuy nhiên, bạn có thể thiết lập một thuộc tính DOS bằng cách sử dụng phương thức setAttribute(Path, String, Object, LinkOption...) như sau:

Path file = ...;
Files.setAttribute(file, "dos:hidden", true);

Phân quyền tập tin POSIX

POSIX là cụm từ viết tắt của Portable Operating System Interface for UNIX (Giao diện Hệ điều hành Di động cho UNIX) và là một bộ tiêu chuẩn IEEE và ISO được thiết kế để đảm bảo khả năng tương tác giữa các thành phần khác nhau của UNIX. Nếu một chương trình phù hợp với các tiêu chuẩn POSIX, nó phải dễ dàng được chuyển đến hệ điều hành POSIX khác.

Bên cạnh chủ sở hữu tập tin và chủ sở hữu nhóm, POSIX hỗ trợ chín phân quyền tập tin: các quyền read, write, và execute áp dụng cho chủ sở hữu tập tin, các thành viên trong cùng một nhóm, và những thành viên khác.

Đoạn mã dưới đây đọc các thuộc tính tập tin POSIX cho một tập tin đã cho và in chúng tại output chuẩn. Đoạn mã này sử dụng các phương thức của giao diện PosixFileAttributes.

Path file = ...;
PosixFileAttributes attr =
    Files.readAttributes(file, PosixFileAttributes.class);
System.out.format("%s %s %s%n",
    attr.owner().getName(),
    attr.group().getName(),
    PosixFilePermissions.toString(attr.permissions()));

Lớp trợ giúp PosixFilePermissions cung cấp một số phương thức hữu ích như sau:

  • Phưng thức toString sử dụng trong đoạn mã trên sẽ chuyển các quyền của tập tin thành một chuỗi ký tự (ví dụ, rw-r-r--).

  • Phương thức fromString chấp nhận một chuỗi đại diện cho các quyền của tập tin và xây dựng một tập các quyền tập tin.

  • Phương thức asFileAttribute chấp nhận một tập các quyền của tập tin và xây dựng một thuộc tính tập tin có thể được truyền cho các phương thức Path.createFile hoặc Path.createDirectory.

Đoạn mã dưới đây đọc các thuộc tính từ một tập tin và tạo ra một tập tin mới, gán thuộc tính từ tập tin ban đầu tới các tập tin mới:

Path sourceFile = ...;
Path newFile = ...;
PosixFileAttributes attrs =
    Files.readAttributes(sourceFile, PosixFileAttributes.class);
FileAttribute<Set<PosixFilePermission>> attr =
    PosixFilePermissions.asFileAttribute(attrs.permissions());
Files.createFile(file, attr);

Phương thức asFileAttribute gộp các quyền cho phép như một FileAttribute. Đoạn mã sau đó cố gắng để tạo ra một tập tin mới theo những quyền này. Lưu ý rằng umask cũng được áp dụng, do đó các tập tin mới có thể được an toàn hơn so với các quyền đã được yêu cầu.

Để thiết lập quyền của một tập tin vào các giá trị đại diện như là một chuỗi mã hóa cứng, ta có thể sử dụng đoạn mã sau:

Path file = ...;
Set<PosixFilePermission> perms =
    PosixFilePermissions.fromString("rw-------");
FileAttribute<Set<PosixFilePermission>> attr =
    PosixFilePermissions.asFileAttribute(perms);
Files.setPosixFilePermissions(file, perms);

Ví dụ Chmod thay đổi các điều khoản của các tập tin theo một cách tương tự như tiện ích chmod.

Thiết lập một tập tin hoặc chủ sở hữu nhóm

Để chuyển một tên thành một đối tượng, ta có thể lưu trữ như là một chủ sở hữu tập tin hoặc một nhóm chủ sở hữu, bạn có thể sử dụng dịch vụ UserPrincipalLookupService. Dịch vụ này sẽ tra một tên hoặc nhóm tên như là một chuỗi và trả về một đối tượng UserPrincipal đại diện cho chuỗi đó. Bạn có thể có được người sử dụng dịch vụ chính cho các hệ thống tập tin mặc định bằng cách sử dụng phương thức FileSystem.getUserPrincipalLookupService.

Đoạn mã sau đây cho thấy cách thiết lập chủ sở hữu tập tin bằng cách sử dụng phương thức setOwner:

Path file = ...;
UserPrincipal owner = file.GetFileSystem().getUserPrincipalLookupService()
        .lookupPrincipalByName("sally");
Files.setOwner(file, owner);

Không có phương thức đặc biệt nào trong lớp Files dùng để để thiết lập nhóm chủ sở hữu. Tuy nhiên, có một cách an toàn để làm như vậy một cách trực tiếp, đó là thông qua view thuộc tính tập tin POSIX, như sau:

Path file = ...;
GroupPrincipal group =
    file.getFileSystem().getUserPrincipalLookupService()
        .lookupPrincipalByGroupName("green");
Files.getFileAttributeView(file, PosixFileAttributeView.class)
     .setGroup(group);
 

Thuộc tính tập tin người dùng định nghĩa

Nếu các thuộc tính tập tin được hỗ trợ bởi sự thực thi hệ thống tập tin của bạn mà không đủ cho nhu cầu của bạn, thì bạn có thể sử dụng UserDefinedAttributeView để tạo và theo dõi các tập tin thuộc tính của riêng bạn.

Một số sự thực thi sẽ ánh xạ khái niệm này với các đặc điểm như các luồng dữ liệu thay thế NTFS và các thuộc tính mở rộng trên hệ thống tập tin như ext3 và ZFS. Hầu hết các trường áp đặt các hạn chế về kích thước, ví dụ như ext3 giới hạn kích thước là 4 kilobyte (4KB).

Kiểu MIME của một tập tin có thể được lưu trữ như là một thuộc tính người dùng định nghĩa bằng cách sử dụng đoạn mã này:

Path file = ...;
UserDefinedFileAttributeView view = Files
    .getFileAttributeView(file, UserDefinedFileAttributeView.class);
view.write("user.mimetype",
           Charset.defaultCharset().encode("text/html");
 

Để đọc các thuộc tính định dạng MIME, bạn sẽ sử dụng đoạn mã này:

Path file = ...;
UserDefinedFileAttributeView view = Files
.getFileAttributeView(file, UserDefinedFileAttributeView.class);
String name = "user.mimetype";
ByteBuffer buf = ByteBuffer.allocate(view.size(name));
view.read(name, buf);
buf.flip();
String value = Charset.defaultCharset().decode(buf).toString();
 

Ví dụ Xdd cho thấy cách làm thế nào để lấy, thiết lập và xóa thuộc tính người dùng định nghĩa.


Lưu ý:  Trong Linux, bạn có thể phải kích hoạt các thuộc tính mở rộng cho các thuộc tính người dùng định nghĩa để làm việc. Nếu bạn nhận được một UnsupportedOperationException khi cố gắng truy cập vào view thuộc tính người dùng định nghĩa, thì bạn cần phải remount các file hệ thống. Các lệnh sau đây sẽ remount phân vùng gốc với các thuộc tính mở rộng cho các hệ thống tập tin ext3 (nếu lệnh này không làm việc với các thành phần khác nhau của Linux, bạn cần tham khảo thêm tài liệu).
$ Sudo mount -o remount, user_xattr /

Nếu bạn muốn thực hiện các thay đổi vĩnh viễn, bạn hãy thêm một điểm đầu vào tới /etc/fstab .


Thuộc tính lưu trữ tập tin

Ta có thể sử dụng lớp FileStore để tìm hiểu thông tin về lưu trữ tập tin, chẳng hạn như còn bao nhiêu không gian có sẵn. Phương thức getFileStore(Path) lấy về file lưu cho tập tin cụ thể.

Đoạn mã sau in ra việc sử dụng không gian cho lưu trữ tập tin, nơi một tập tin cụ thể cư trú:

Path file = ...;
FileStore store = Files.getFileStore(file);

long total = store.getTotalSpace() / 1024;
long used = (store.getTotalSpace() -
             store.getUnallocatedSpace()) / 1024;
long avail = store.getUsableSpace() / 1024;

 

Ví dụ lớp DiskUsage sử dụng API này để in các thông tin về không gian đĩa cho tất cả các vùng lưu trữ trong hệ thống tập tin mặc định.Ví dụ này sử dụng phương thức getFileStores trong lớp FileSystem để lấy tất cả các vùng lưu trữ cho các hệ thống tập tin.

» Tiếp: Đọc, ghi và tạo tập tin
« Trước: Di chuyển tập tin hoặc thư mục
Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực
Copied !!!