Files.exists(path) 和 path.toFile().exists() 为同一文件提供不同的结果

2022-09-04 03:30:32

我得到的结果是 Windows 上的本地文件。我可以在Windows资源管理器中看到此文件,尽管我有(随机)修改的权限,也许权限没有意义。Files.exists(path)path.toFile().exists()

但是,这并不能解释为什么旧方法返回 true,而新方法返回 false。该文件肯定存在,但也许它对运行Java代码的用户是不可见的,所以我不确定正确的答案应该是什么。我也看不到如何查看哪个用户正在运行代码,计算机上只有一个真正的用户Paul,但我想知道是否以管理员身份运行是否会影响事情。

System.out.println("Path Exists(1):"+Files.exists(path));
System.out.println("Path Exist(2) :"+path.toFile().exists());

Path Exists(1):false
Path Exist(2) :true

System.out.println("Path readable(3) :"+Files.isReadable(path));
System.out.println("Path readable(4):"+path.toFile().canRead());

以同样的方式给予

Path readable(3) :false
Path readable(4):true

权限输出

File C:\Code\jthink\opensrc\jaudiotagger\testdata\test157.dsf permissions
owner:PCLAPTOP\Paul
NT AUTHORITY\SYSTEM:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:DENY
BUILTIN\Administrators:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:DENY
BUILTIN\Administrators:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:ALLOW
NT AUTHORITY\SYSTEM:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:ALLOW
BUILTIN\Users:READ_DATA/READ_NAMED_ATTRS/EXECUTE/READ_ATTRIBUTES/READ_ACL/SYNCHRONIZE:ALLOW
NT AUTHORITY\Authenticated Users:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/READ_ATTRIBUTES/WRITE_ATTRIBUTES/DELETE/READ_ACL/SYNCHRONIZE:ALLOW


c:\Code\jthink\opensrc\jaudiotagger>attrib C:\Code\jthink\opensrc\jaudiotagger\testdata\test157.dsf
A    R       C:\Code\jthink\opensrc\jaudiotagger\testdata\test157.dsf

更新我没有结论,但认为这些信息可能是有用的。

我在IntelliJ IDE中运行代码而没有启用IDE以管理员身份运行程序选项,启用此功能确实会导致Java应用程序也获得管理员权限。

有趣的是,对于另一个文件,我没有添加任何DENY权限,我只是禁用了继承权限并从所有组中删除读取权限。然后,当我以用户身份运行而没有以管理员身份运行时,它无法读取文件,并且此代码也无法输出任何信息

AclFileAttributeView view = Files.getFileAttributeView(path, AclFileAttributeView.class);
if (view != null)
{
    sb.append("Owner:"+view.getOwner().getName()+"**");
    for (AclEntry acl : view.getAcl())
    {
        sb.append(acl.principal()+"**");
        for(AclEntryPermission aep:acl.permissions())
        {
            sb.append(aep.toString() + "**");
        }
    }
}

但是当我在运行程序作为管理员的情况下运行时,它仍然无法读取该文件,但是上面的代码现在确实输出了一些权限,如下所示:

所有者:内置\管理员

NT AUTHORITY\SYSTEM:WRITE_DATA/APPEND_DATA/WRITE_NAMED_ATTRS/WRITE_ATTRIBUTES/SYNCE:ALLOW PCLAPTOP\Paul:WRITE_DATA/APPEND_DATA/WRITE_NAMED_ATTRS/WRITE_ATTRIBUTES/SYNCE:ALLOW 内置\管理员:WRITE_DATA/APPEND_DATA/WRITE_NAMED_ATTRS/WRITE_ATTRIBUTES/SYNCE:ALLOW

正如你所看到的,即使没有或选项,他们可以输出权限,而之前他们不能,也许是由于BUILDIN / Administraor被返回为所有者。AdministratorsREADREAD PERMISSIONS


答案 1

尝试阅读以下内容:https://docs.oracle.com/javase/tutorial/essential/io/check.html

它指出,返回 false 并不意味着它不存在,所以是的,它似乎存在权限问题。也试试,看看它会返回什么。如果它是 false,则表示无法确定该文件是否存在,但如果它返回 true,则代码中可能存在一些问题。Files.exists(path)Files.notExists(path)

尝试从命令行而不是 netbean 运行文件。如果你不知道如何做到这一点,你可以搜索谷歌,这上面有很多东西,但基本上你想做的是编译.java文件,然后运行它。使用普通命令提示符和以管理员身份打开的命令提示符执行此操作,然后查看您获得的内容。javac myfile.javajava myfile


答案 2

这是两种不同的方法:Files.exists() 和 path.toFile().exists()。

Files.exists() 定义了由此抽象路径名表示的文件是否存在。换句话说,该文件存在,并且用户对它具有读取访问权限。

path.toFile().exists() 表示该文件存在,则不能保证子序列访问会成功。换句话说,文件存在而不检查用户是否具有读取访问权限。

这实际上取决于运行程序的用户。当你在你的ID(保罗)下工作时,它工作正常。特别是在命令行中,您可以在其中使用ATTRIB命令。

但是,当您使用其他应用程序来运行代码时,这取决于系统配置。在应用程序内运行此 ATTRIB 或类似命令,您将看到。

我想你在IIS下运行一些网站。这种方式通常是为系统中的最低级别的用户配置的,几乎没有防止安全中断的权限。通常是每个人或NT权威。正如我所看到的,这个特定的访问权限没有读取您的文件的权限

NT AUTHORITY\SYSTEM:READ_DATA/...:DENY

当然,你有2个不同的答案 - FALSE:运行应用程序使用哪个ID的用户无法读取此文件,TRUE:文件物理存在。

更改应用程序的运行 ID 或向此特定文件的每个人(包括其路径中的所有目录)授予 READ 访问权限,您将在这两种方法中得到相同的结果,这两种方法检查不同的含义。