这些Java教程是针对JDK 8编写的。本页面中描述的示例和实践不利用后续版本中引入的改进,并可能使用不再可用的技术。
有关Java SE 9及其后续版本中更新的语言功能的概述,请参阅Java语言更改。
有关所有JDK版本的新功能、增强功能和已删除或已弃用选项的信息,请参阅JDK发布说明。
元数据的定义是“关于其他数据的数据”。在文件系统中,数据包含在其文件和目录中,而元数据则跟踪每个对象的信息:它是一个普通文件、一个目录还是一个链接?它的大小、创建日期、最后修改日期、文件所有者、组所有者和访问权限是什么?
文件系统的元数据通常被称为其文件属性。Files
类包含用于获取文件的单个属性或设置属性的方法。
size(Path)
isDirectory(Path, LinkOption)
Path
isRegularFile(Path, LinkOption...)
Path
isSymbolicLink(Path)
Path
isHidden(Path)
Path
getLastModifiedTime(Path, LinkOption...)
setLastModifiedTime(Path, FileTime)
getOwner(Path, LinkOption...)
setOwner(Path, UserPrincipal)
getPosixFilePermissions(Path, LinkOption...)
setPosixFilePermissions(Path, Set<PosixFilePermission>)
getAttribute(Path, String, LinkOption...)
setAttribute(Path, String, Object, LinkOption...)
如果一个程序需要同时获取多个文件属性,使用逐个检索属性的方法可能效率低下。重复访问文件系统以获取单个属性可能会对性能产生负面影响。因此,Files
类提供了两种readAttributes
方法,可以在一次批量操作中获取文件的属性。
方法 | 说明 |
---|---|
readAttributes(Path, String, LinkOption...) |
以批量操作的方式读取文件的属性。String 参数指定要读取的属性。 |
readAttributes(Path, Class<A>, LinkOption...) |
以批量操作的方式读取文件的属性。Class<A> 参数是请求的属性类型,方法返回该类的对象。 |
在展示readAttributes
方法的示例之前,应该提到不同的文件系统对于应该跟踪的属性有不同的概念。因此,相关的文件属性被分组到视图中。一个视图对应于特定的文件系统实现,例如POSIX或DOS,或者对应于常见的功能,例如文件所有权。
支持的视图如下:
BasicFileAttributeView
- 提供了所有文件系统实现都必须支持的基本属性的视图。DosFileAttributeView
- 通过标准的四位DOS属性扩展了基本属性视图,这些属性在支持DOS属性的文件系统上得到支持。PosixFileAttributeView
- 通过在支持POSIX系列标准(如UNIX)的文件系统上支持的属性扩展了基本属性视图。这些属性包括文件所有者、组所有者和九个相关的访问权限。FileOwnerAttributeView
- 支持任何支持文件所有者概念的文件系统实现。AclFileAttributeView
- 支持读取或更新文件的访问控制列表(ACL)。支持NFSv4 ACL模型。任何具有良好定义的映射到NFSv4模型的ACL模型(如Windows ACL模型)也可能得到支持。UserDefinedFileAttributeView
- 允许支持用户定义的元数据。此视图可以映射到系统支持的任何扩展机制。例如,在Solaris操作系统中,您可以使用此视图来存储文件的MIME类型。特定的文件系统实现可能只支持基本文件属性视图,或者可能支持其中的多个文件属性视图。文件系统实现可能支持此API中未包含的其他属性视图。
在大多数情况下,您不需要直接处理任何FileAttributeView
接口。(如果您确实需要直接使用FileAttributeView
,可以通过getFileAttributeView(Path, Class<V>, LinkOption...)
方法访问它。)
readAttributes
方法使用泛型,可用于读取任何文件属性视图的属性。本页其余部分的示例使用readAttributes
方法。
本节的剩余部分涵盖以下主题:
如前所述,要读取文件的基本属性,可以使用Files.readAttributes
方法之一,它会一次性读取所有基本属性。这比单独访问文件系统以读取每个属性要高效得多。可变参数当前支持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以外,其他文件系统(如Samba)也支持DOS文件属性。以下代码片段使用了DosFileAttributes
类的方法。
Path file = ...; try { DosFileAttributes attr = Files.readAttributes(file, DosFileAttributes.class); System.out.println("isReadOnly是 " + attr.isReadOnly()); System.out.println("isHidden是 " + attr.isHidden()); System.out.println("isArchive是 " + attr.isArchive()); System.out.println("isSystem是 " + attr.isSystem()); } catch (UnsupportedOperationException x) { System.err.println("不支持DOS文件属性:" + x); }
然而,你可以使用setAttribute(Path, String, Object, LinkOption...)
方法设置DOS属性,如下所示:
Path file = ...; Files.setAttribute(file, "dos:hidden", true);
POSIX是Portable Operating System Interface for UNIX的缩写,是一组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的Alternative Data Streams和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
方法来获取文件系统的所有文件存储。