Java帮助程序类java.nio.file.Files
具有访问文件属性的方法。一些类方法遵循符号链接(所有带有LinkOption
参数的方法),而对于其他一些方法,不清楚是否遵循符号链接(没有LinkOption
参数的方法)。
这些是遵循符号链接的方法:Files.isDirectory(Path, LinkOption...)
Files.isRegular(Path, LinkOption...)
Files.getAttribute(Path, String, LinkOption...)
Files.getLastModified(Path, LinkOption...)
Files.getOwner(Path, LinkOption...)
Files.getPosixFilePermission(Path, LinkOption...)
对于其他一些方法,确定它们是否遵循符号链接并不明显(在Javadoc中没有LinkOption...
参数并且没有提及符号链接):Files.isSymbolicLink(Path)
Files.isExecutable(Path)
Files.isReadable(Path)
Files.isWritable(Path)
Files.isHidden(Path)
Files.size(Path)
Files.getFileStore(Path)
跟随符号链接的不带LinkOption...
参数的方法有哪些,为什么?
最佳答案
TLDR:在大多数情况下,这似乎是FileSystemProvider
实现方式的选择,即不遵循符号链接(这可以回答“为什么”问题)。符号链接是:
已关注:Files.size(Path)
主要关注:Files.getFileStore(Path)
:在Windows和Linux上紧随其后,在Jimfs上不紧随其后
未遵循:Files.isSymbolic(Path)
通常不遵循:Files.isExecutable(Path)
:在Windows和Unix上不遵循,但在Jimfs上遵循Files.isReadable(Path)
:在Windows和Unix上不遵循,但在Jimfs上遵循
完全特定于实现:Files.isWritable(Path)
:在Windows上遵循,但在Unix上没有Files.isHidden(Path)
:在Windows上遵循,但在Unix上没有
您可以通过调用Files.readAttributes(Path, Class, LinkOption...)
并使用返回的属性来确定是否跟随符号链接。Files.isSymbolic(Path)
不跟随符号链接
对于Files.isSymbolic(Path)
,原因很明显:如果默认情况下该方法遵循符号链接,则该方法将始终返回false
。Files.isHidden(Path)
在Windows上遵循符号链接,但在Unix上不遵循
从方法签名来看,我们可能认为该方法未遵循符号链接(因为没有LinkOption...
参数)。但是,这并不是很明显。Files.isHidden(Path)
方法委托给java.nio.file.spi.FileSystemProvider.isHidden(Path)
的实现,并且无论该方法是否遵循符号链接,javadoc均未指定。
在Windows上,它是implemented by following symbolic links,请参见第465行(true
调用中的WindowsFileAttributes.get(file, true)
参数指示遵循符号链接):
@Override
public boolean isHidden(Path obj) throws IOException {
WindowsPath file = WindowsPath.toWindowsPath(obj);
file.checkRead();
WindowsFileAttributes attrs = null;
try {
attrs = WindowsFileAttributes.get(file, true);
} catch (WindowsException x) {
x.rethrowAsIOException(file);
}
// DOS hidden attribute not meaningful when set on directories
if (attrs.isDirectory())
return false;
return attrs.isHidden();
}
在Unix上,此方法为implemented without following symbolic links(它仅检查文件以“。”开头):
@Override
public boolean isHidden(Path obj) {
UnixPath file = UnixPath.toUnixPath(obj);
file.checkRead();
UnixPath name = file.getFileName();
if (name == null)
return false;
return (name.asByteArray()[0] == '.');
}
因此,我们可以得出结论,这是特定于实现的。
Files.isExecutable(Path)
在大多数文件系统中不遵循符号链接此方法委托给
Files.isAccessible(Path, AccessMode.EXECUTE)
,后者委托给FileSystemProvider.checkAccess(Path, AccessMode...)
方法。在Windows上,
WindowsFileSystemProvider.checkAccess(Path, AccessMode...)
方法委托给java.lang.SecurityManager
,后者确定文件是否可执行。 AFAIK,SecurityManager
不跟随符号链接,因此我们可以假定Files.isExecutable(Path)
在Windows上不跟随符号链接。在Unix上,
UnixFileSystemProvider.checkAccess(Path, AccessMode...)
方法也委托给SecurityManager
,我们可以假定Files.isExecutable(Path)
在Unix上也不遵循符号链接。在Jimfs(来自Google的内存中文件系统)上,调用将委托给
com.google.common.jimfs.FileSystemView.checkAccess(JimfsPath)
,该链接遵循符号链接(即使Jimfs不支持访问控制):public void checkAccess(JimfsPath path) throws IOException {
// just check that the file exists
lookUpWithLock(path, Options.FOLLOW_LINKS).requireExists(path);
}
因此,我们可以得出结论,根据文件系统,
Files.isExecutable(Path)
可能跟随符号链接,但在大多数情况下(Unix + Windows)不会。Files.isReadable(Path)
在大多数文件系统上不遵循符号链接Files.isReadable(Path)
的实现与isExecutable(Path)
的实现非常相似:在Unix和Windows上不遵循链接,但在Jimfs上遵循链接。Files.isWritable(Path)
对于
Files.isExecutable(Path)
,isWritable(Path)
方法委托给FileSystemProvider.checkAccess(Path)
。在Windows上,这需要确定文件是否具有只读属性,这是通过以下链接完成的(请参见上面的
WindowsFileSystemProvider
代码)。在Unix上,显然无需跟随符号链接即可完成此操作(请参见上面的
UnixFileSystemProvider
)。因此,我们可以得出结论,这是特定于实现的。
Files.size(Path)
跟随符号链接该实现委托给
readAttributes
,因此它遵循所有文件系统实现的符号链接:public static long size(Path path) throws IOException {
return readAttributes(path, BasicFileAttributes.class).size();
}
Files.getFileStore(Path)
该方法委托给
FileSystemProvider.getFileStore(Path)
方法。在Windows上,它使用跟随符号链接的
WindowsFileStore.create(Path)
(请参阅true
参数):static WindowsFileStore create(WindowsPath file) throws IOException {
try {
// if the file is a link then GetVolumePathName returns the
// volume that the link is on so we need to call it with the
// final target
String target = WindowsLinkSupport.getFinalPath(file, true);
...
在Unix上,
FileSystemProvider.getFileStore(Path)
方法是抽象的,由子类实现,例如[LinuxFileSystem][3]
:@Override
LinuxFileStore getFileStore(UnixPath path) throws IOException {
return new LinuxFileStore(path);
}
此类通过获取带有以下链接的属性(
UnixFileStore
调用中的true
参数)来构造UnixFileAttributes.get()
:private static long devFor(UnixPath file) throws IOException {
try {
return UnixFileAttributes.get(file, true).dev();
} catch (UnixException x) {
x.rethrowAsIOException(file);
return 0L; // keep compiler happy
}
}
在Jimfs中,
FileStore
似乎是在创建时附加到文件的,因此,看起来没有遵循链接。因此,我们可以得出结论,在大多数文件系统实现中,
Files.getFileStore(Path)
使用符号链接。
关于java - 哪些java.nio.file.Files方法遵循符号链接(symbolic link),哪些不遵循符号链接(symbolic link)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55894781/