【发布时间】:2019-05-16 10:24:42
【问题描述】:
来自Files.isHidden(Path) 的文档(强调我的):
判断文件是否被视为隐藏。隐藏的确切定义取决于平台或提供商。例如,在 UNIX 上,如果文件名以句点字符 ('.') 开头,则认为文件被隐藏。 在 Windows 上,如果文件不是目录并且设置了 DOS 隐藏属性,则认为文件是隐藏的。
根据实现的不同,此方法可能需要访问文件系统以确定文件是否被视为隐藏。
由此我可以理解什么预期的行为。然而,为什么这是预期的行为?
我想知道的原因是Files.isHidden、DosFileAttributes.isHidden 和 Windows 的文件资源管理器之间的行为差异。例如,我可以进入 文件资源管理器 并将一个目录设置为隐藏,它将不再显示(除非我将其配置为显示隐藏项)。如果我测试是否使用 Java 隐藏了所述目录,则 Files.isHidden 返回 false 和 DosFileAttributes.isHidden 返回 true。您可以使用以下代码对此进行测试:
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.DosFileAttributes;
public class Main {
public static void main(String[] args) throws Exception {
final var directory = Path.of(args[0]).toAbsolutePath().normalize();
final var store = Files.getFileStore(directory);
final var dosAttrs = Files.readAttributes(directory, DosFileAttributes.class);
System.out.println("Directory : " + directory);
System.out.println("FileStore : " + store.name() + " [" + store.type() + "]");
System.out.println("Hidden (Files): " + Files.isHidden(directory));
System.out.println("Hidden (Dos) : " + dosAttrs.isHidden());
}
}
注意:我使用的是 Windows 10 和 OpenJDK 11.0.1。我的文件系统是 NTFS。
运行这个:
java Main.java C:\path\to\hidden\directory
我明白了:
Directory : C:\path\to\hidden\directory
FileStore : OS [NTFS]
Hidden (Files): false
Hidden (Dos) : true
注意:此行为似乎是 WindowsFileSystemProvider 的一部分。方法Files.isHidden(Path) 只是将调用转发给参数的FileSystem 的提供者。实现基本上是:
DosFileAttributes attrs = ...; // get attributes
return !attrs.isDirectory() && attrs.isHidden();
我发现这个(non)-issue (JDK-8170334) 有一条评论说:
我认为我们这里没有错误,因为 hidden 属性对目录没有意义。
然而,Windows 上的核心软件 File Explorer 的行为就像 hidden 属性在目录上 not 毫无意义。再说一遍,为什么 Windows 上的 Java 实现会考虑 Path 是否指向目录?还是 Java 是正确的,而 文件资源管理器 正在做非标准的事情?
我倾向于认为 File Explorer 是正确的,因为 CMD(通过 dir)和 PowerShell(通过 Get-ChildItem ) 也不会列出隐藏目录;除非指定了适当的选项,否则不会。
【问题讨论】:
-
我不是 Java 开发人员,也不打算深入研究 JDK 设计问题,但从表面上看,这在我看来就像有人混淆了 hidden 和 readonly 属性。 Windows shell (Explorer) 会忽略在目录上设置 readonly 属性,因为它没有用。它所做的只是防止删除一个空目录。相比之下,在 Linux/BSD 中的目录上设置不可变属性(通过 chattr / chflags,通常作为超级用户)可以防止以任何方式修改目录。
-
在我的盒子 "C:\" 上使用 dosAttrs.isHidden() 时要小心,返回 True
-
@Stig 此处相同(Java 12.0.1,Windows 10)。但是,PowerShell 还说
"C:\"是隐藏的,所以这可能是预期的行为。 -
我同意这不是一个错误,但它会让大多数人感到惊讶。
标签: java windows nio hidden-files