Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
metadata (元数据) 的定义是“关于其他数据的数据”。使用文件系统,数据包含在其文件和目录中,元数据跟踪有关每个对象的信息:它是常规文件,目录还是链接?它的大小,创建日期,上次修改日期,文件所有者,组所有者和访问权限是什么?
文件系统的元数据通常称为其 file attributes (文件属性)。Files
类包括可用于获取文件的单个属性或设置属性的方法。
方法 | 注释 |
---|---|
size(Path) |
以字节为单位返回指定文件的大小。 |
isDirectory(Path, LinkOption) |
如果指定的 Path 找到的文件是目录,则返回 true。 |
isRegularFile(Path, LinkOption...) |
如果指定的 Path 找到的文件是常规文件,则返回 true。 |
isSymbolicLink(Path) |
如果指定的 Path 找到的文件是符号链接,则返回 true。 |
isHidden(Path) |
如果指定的 Path 找到的文件是系统认为隐藏的文件,则返回 true。 |
getLastModifiedTime(Path, LinkOption...) setLastModifiedTime(Path, FileTime) |
返回或设置指定文件的上次修改时间。 |
getOwner(Path, LinkOption...) setOwner(Path, UserPrincipal) |
返回或设置文件的所有者。 |
getPosixFilePermissions(Path, LinkOption...) setPosixFilePermissions(Path, Set<PosixFilePermission>) |
返回或设置文件的 POSIX 文件权限。 |
getAttribute(Path, String, LinkOption...) setAttribute(Path, String, Object, LinkOption...) |
返回或设置文件属性的值。 |
如果程序在同一时间需要多个文件属性,则使用获取单个属性的方法可能效率低下。重复访问文件系统以获取单个属性可能会对性能产生负面影响。因此,Files
类提供了两个 readAttributes
方法,用于在一次批量操作中获取文件的属性。
方法 | 注释 |
---|---|
readAttributes(Path, String, LinkOption...) |
将文件的属性读取为批量操作。String 参数标识要读取的属性。 |
readAttributes(Path, Class<A>, LinkOption...) |
将文件的属性读取为批量操作。Class<A> 参数是请求的属性类型,该方法返回该类的对象。 |
在显示 readAttributes
方法的示例之前,应该提到不同的文件系统对于应该跟踪哪些属性有不同的概念。因此,相关文件属性被组合在一起成为视图。view 映射到特定的文件系统实现,例如 POSIX 或 DOS,或者映射到常用功能,例如文件所有权。
支持的视图如下:
BasicFileAttributeView
–提供所有文件系统实现都需要支持的基本属性的视图。DosFileAttributeView
–使用支持 DOS 属性的文件系统支持的标准四位继承基本属性视图。PosixFileAttributeView
–使用支持 POSIX 标准系列(如 UNIX)的文件系统支持的属性继承基本属性视图。这些属性包括文件所有者,组所有者和九个相关的访问权限。FileOwnerAttributeView
–支持文件所有者概念的任何文件系统实现。AclFileAttributeView
–支持读取或更新文件的访问控制列表(ACL)。支持 NFSv4 ACL 模型。也可以支持任何 ACL 模型,例如 Windows ACL 模型,它具有定义到 NFSv4 模型的定义良好的映射。UserDefinedFileAttributeView
–支持用户定义的元数据。此视图可以映射到系统支持的任何扩展机制。例如,在 Solaris OS 中,你可以使用此视图来存储文件的 MIME 类型。特定文件系统实现可能仅支持基本文件属性视图,或者它可能支持其中几个文件属性视图。文件系统实现可能支持此 API 中未包含的其他属性视图。
在大多数情况下,你不必直接处理任何 FileAttributeView
接口。(如果确实需要直接使用 FileAttributeView
,可以通过 getFileAttributeView(Path, Class<V>, LinkOption...)
方法访问它。)
readAttributes
方法使用泛型,可用于读取任何文件属性视图的属性。本页其余部分中的示例使用 readAttributes
方法。
本节的其余部分包括以下主题:
如前所述,要读取文件的基本属性,可以使用 Files.readAttributes
方法之一,该方法在一个批量操作中读取所有基本属性。这比单独访问文件系统以读取每个单独的属性要有效得多。varargs 参数目前支持 LinkOption
枚举,NOFOLLOW_LINKS
。如果不希望遵循符号链接,请使用此选项。
creationTime
,lastModifiedTime
和 lastAccessTime
。在特定实现中可能不支持任何这些时间戳,在这种情况下,相应的访问器方法返回特定于实现的值。支持时,时间戳将作为 FileTime
对象返回。
以下代码段读取并打印给定文件的基本文件属性,并使用 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());
除了此示例中显示的访问器方法之外,还有一个 fileKey
方法,该方法返回唯一标识文件的对象,如果没有可用的文件密钥则返回 null
。
以下代码段设置上次修改时间(以毫秒为单位):
Path file = ...; BasicFileAttributes attr = Files.readAttributes(file, BasicFileAttributes.class); long currentTime = System.currentTimeMillis(); FileTime ft = FileTime.fromMillis(currentTime); Files.setLastModifiedTime(file, ft); }
除 DOS 之外的文件系统也支持 DOS 文件属性,例如 Samba。以下代码段使用 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); }
但是,你可以使用 setAttribute(Path, String, Object, LinkOption...)
方法设置 DOS 属性,如下所示:
Path file = ...; Files.setAttribute(file, "dos:hidden", true);
POSIX 是适用于 UNIX 的可移植操作系统接口(Portable Operating System Interface)的首字母缩写,是一组 IEEE 和 ISO 标准,旨在确保不同版本的 UNIX 之间的互操作性。如果程序符合这些 POSIX 标准,则应该可以轻松移植到其他符合 POSIX 标准的操作系统。
除文件所有者和组所有者外,POSIX 还支持九种文件权限:文件所有者,同一组成员和“其他人”的读取,写入和执行权限。
以下代码段读取给定文件的 POSIX 文件属性并将其打印到标准输出。该代码使用 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()));
PosixFilePermissions
助手类提供了几种有用的方法,如下所示:
toString
方法将文件权限转换为字符串(例如,rw-r--r--
)。fromString
方法接受表示文件权限的字符串,并构造文件权限的 Set
。asFileAttribute
方法接受文件权限的 Set
,并构造可以传递给 Path.createFile
或 Path.createDirectory
方法。以下代码段从一个文件中读取属性并创建一个新文件,将原始文件中的属性分配给新文件:
Path sourceFile = ...; Path newFile = ...; PosixFileAttributes attrs = Files.readAttributes(sourceFile, PosixFileAttributes.class); FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(attrs.permissions()); Files.createFile(file, attr);
asFileAttribute
方法将权限包装为 FileAttribute
。然后,代码尝试使用这些权限创建新文件。请注意,umask
也适用,因此新文件可能比请求的权限更安全。
要将文件的权限设置为表示为硬编码字符串的值,可以使用以下代码:
Path file = ...; Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rw-------"); FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms); Files.setPosixFilePermissions(file, perms);
示例以类似于 Chmod
chmod
实用程序的方式递归更改文件的权限。
要将名称转换为可以存储为文件所有者或组所有者的对象,可以使用 UserPrincipalLookupService
服务。此服务将名称或组名称查找为字符串,并返回表示该字符串的 UserPrincipal
对象。你可以使用 FileSystem.getUserPrincipalLookupService
方法获取默认文件系统的用户主体查找服务。
以下代码段显示了如何使用 setOwner
方法设置文件所有者:
Path file = ...; UserPrincipal owner = file.GetFileSystem().getUserPrincipalLookupService() .lookupPrincipalByName("sally"); Files.setOwner(file, owner);
Files
类中没有用于设置组所有者的特殊方法。但是,直接执行此操作的安全方法是通过 POSIX 文件属性视图,如下所示:
Path file = ...; GroupPrincipal group = file.getFileSystem().getUserPrincipalLookupService() .lookupPrincipalByGroupName("green"); Files.getFileAttributeView(file, PosixFileAttributeView.class) .setGroup(group);
如果文件系统实现支持的文件属性不足以满足你的需要,则可以使用 UserDefinedAttributeView
创建和跟踪自己的文件属性。
一些实现将此概念映射到 NTFS 备用数据流等功能以及文件系统(如 ext3 和 ZFS)上的继承属性。大多数实现都对值的大小施加了限制,例如,ext3 将大小限制为 4 千字节。
通过使用以下代码片段,可以将文件的 MIME 类型存储为用户定义的属性:
Path file = ...; UserDefinedFileAttributeView view = Files .getFileAttributeView(file, UserDefinedFileAttributeView.class); view.write("user.mimetype", Charset.defaultCharset().encode("text/html");
要阅读 MIME 类型属性,你可以使用以下代码段:
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();
示例显示了如何获取,设置和删除用户定义的属性。Xdd
UnsupportedOperationException
,则需要重新装入文件系统。以下命令使用 ext3 文件系统的继承属性重新安装根分区。如果此命令不适合你的 Linux 风格,请参阅文档。
$ sudo mount -o remount,user_xattr /
如果要使更改成为永久更改,请在 /etc/fstab
中添加一个条目。
你可以使用 FileStore
类来了解有关文件存储的信息,例如可用空间大小。getFileStore(Path)
方法获取指定文件的文件存储。
以下代码段打印特定文件所在的文件存储的空间使用情况:
Path file = ...; FileStore store = Files.getFileStore(file); long total = store.getTotalSpace() / 1024; long used = (store.getTotalSpace() - store.getUnallocatedSpace()) / 1024; long avail = store.getUsableSpace() / 1024;
DiskUsage
示例使用此 API 打印默认文件系统中所有存储的磁盘空间信息。此示例使用 FileSystem
类中的 getFileStores
方法来获取文件系统的所有文件存储。