Java 为什么Windows上的目录Files.ishiden(Path)返回false?

Java 为什么Windows上的目录Files.ishiden(Path)返回false?,java,windows,nio,hidden-files,Java,Windows,Nio,Hidden Files,从(emphasismine)的文档中: 说明文件是否被视为隐藏。隐藏的确切定义取决于平台或提供程序。例如,在UNIX上,如果文件名以句点字符('.')开头,则认为文件是隐藏的在Windows上,如果文件不是目录并且设置了DOS HINDED属性,则认为该文件是隐藏的。 根据实现情况,此方法可能需要访问文件系统以确定文件是否被视为隐藏 从这一点我可以理解预期的行为是什么。然而,为什么这是预期的行为 我想知道的原因是Files.ishiden、DosFileAttributes.ishiden和W

从(emphasismine)的文档中:

说明文件是否被视为隐藏。隐藏的确切定义取决于平台或提供程序。例如,在UNIX上,如果文件名以句点字符('.')开头,则认为文件是隐藏的在Windows上,如果文件不是目录并且设置了DOS HINDED属性,则认为该文件是隐藏的。

根据实现情况,此方法可能需要访问文件系统以确定文件是否被视为隐藏

从这一点我可以理解预期的行为是什么。然而,为什么这是预期的行为

我想知道的原因是
Files.ishiden
DosFileAttributes.ishiden
和Windows的文件资源管理器之间的行为差异。例如,我可以进入文件资源管理器,将一个目录设置为隐藏,它将不再显示(除非我将其配置为显示隐藏项)。如果我测试所述目录是否用Java隐藏,则
Files.ishiden
返回
false
DosFileAttributes.ishiden
返回
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());
  }

}

注意:我使用的是Windows10和OpenJDK11.0.1。我的文件系统是NTFS


使用以下命令运行此命令:

java Main.java C:\path\to\hidden\directory
我得到:

目录:C:\path\to\hidden\Directory
文件存储:OS[NTFS]
隐藏(文件):false
隐藏(Dos):真

注意:此行为似乎是
WindowsFileSystemProvider
的一部分。方法
Files.ishiden(Path)
只是将调用转发给参数的
文件系统的提供程序。实施基本上是:

DosFileAttributes attrs=…;//获取属性
回来!attrs.isDirectory()和&attrs.ishiden();

我发现(JDK-8170334)中有一条评论说:

我认为这里没有bug,因为隐藏属性在目录中没有意义

然而,Windows上的核心软件文件资源管理器的行为就像隐藏属性在目录上并非毫无意义。那么,为什么Windows上的Java实现要考虑路径是否指向目录呢?或者Java是正确的,而文件资源管理器正在做非标准的事情

我倾向于认为文件资源管理器是正确的,因为CMD(通过
dir
)和PowerShell(通过
getchilditem
)也不会列出隐藏的目录;除非指定了适当的选项,否则不会。我检查了Microsoft for Windows平台提供的文件属性。它表示如果设置了attribute
FILE\u attribute\u HIDDEN=2(0x2)

文件或目录被隐藏。它不包括在普通目录列表中

正如我在类
sun.nio.fs.WindowsConstants
中看到的,DosFileAttributes.isHidden()方法使用了相同的值定义-
public static final int FILE_ATTRIBUTE_HIDDEN=0x00000002应该与Windows可用的属性一一对应,因此通常目录的
hidden
标志应该与常规文件的工作方式相同。
就操作系统/文件系统集成而言,这种行为似乎是不正确的

我不是Java开发人员,我也不打算深入研究JDK设计问题,但在表面上看,似乎有人在混淆隐藏属性和只读属性。Windows shell(资源管理器)会忽略在目录上设置readonly属性,因为它没有用处。它所做的只是防止删除空目录。相反,在Linux/BSD中设置目录的immutable属性(通过chattr/chflags,通常作为超级用户)可以防止以任何方式修改目录。在我的框“C:\”中使用dosAttrs.ishiden()时要小心True@Stig这里也一样(Java12.0.1,Windows10)。但是,PowerShell还说
“C:\”
是隐藏的,因此这可能是预期的行为。我同意这不是一个bug,但它会让大多数人感到惊讶。正在更正
文件。ishiden()
bug将破坏现有的Windows Java应用程序,这些应用程序尽职尽责地遵循Windows系统上隐藏目录的bug定义,而不进一步检查
DosFileAttributes.ishiden()
。这可能就是Java API开发人员不想让它成为问题的原因,因为我们仍然可以使用
DosFileAttributes.ishiden()
来构建正确的行为。我最后提交了一个错误报告:。我们将看到这一点,但@ecle可能是正确的,并且由于他们在评论中解释的原因,它不会被修复;如果它没有像其他两个bug报告那样以“不是问题”的形式关闭的话。结果证明它毕竟是一个bug。报告说它是用Java13修复的。