当文件存在时,Java 17 路径存在()花费非常长的时间

问题描述 投票:0回答:1

我在 Windows 10 上使用 Java 17。我有一组采用这种形式的目录:

data/dir-0
data/dir-1
data/dir-2
…
data/dir-999

我使用变量

0
对整数
999
i
进行循环。在每个循环中,我只是检查子目录中是否有
foo.bar
文件:

Path foobarFile = dataDir.resolve("dir-"+i);
if(Files.exists(fooBarFile)) {
  //do something; currently does nothing
}

如果所有

data/dir-*
目录都是空的,它们就会爆炸,整个循环在一瞬间结束(几分之一秒)。

但是,如果某些

data/dir-*
目录包含
foo.bar
文件,则循环会加速遍历空目录,直到真正找到
foo.bar
文件,然后突然每个
exists(fooBarFile)
调用都需要几乎半秒! (每次调用都花费相同的时间,就好像有一些时钟在计数一样。)

然后它变得更奇怪:如果我在没有任何更改的情况下再次运行该程序,它会以某种方式“记住它离开的位置”,并且会加速遍历所有目录,直到到达之前未检查过的目录。然后每个

exists(fooBarFile)
调用几乎需要一秒钟。

请注意,这会在 Eclipse 内和命令行中发生。

为什么文件实际存在时

exists(fooBarFile)
需要这么长时间?它如何“记住”在运行应用程序之间检查了哪些内容?我很困惑。

更新: 显然,这里是 Java 17 如何检查 Windows 路径是否存在,在

sun.nio.fs.WindowsFileSystemProvider.checkReadAccess(WindowsPath file)
中:


try {
  Set<OpenOption> opts = Collections.emptySet();
  FileChannel fc = WindowsChannelFactory
      .newFileChannel(file.getPathForWin32Calls(),
          file.getPathForPermissionCheck(), opts, 0L);
  fc.close();
} catch (WindowsException exc) {
…

是的,看来 Java 通过打开文件通道来判断文件是否存在! 😦😭

告诉我事实并非如此。我只需要知道文件是否存在,这样我就知道是否需要生成它。我不需要检查读取访问权限或其他任何内容。难道就没有更有效的方法吗?此外,在最近配备 SSD 的机器上,打开和关闭通道肯定不会花费一秒钟的时间,不是吗??

java file file-exists
1个回答
0
投票

这似乎与 Windows Defender 有关。我转到 Windows 安全中心 > 病毒和威胁防护 > 病毒和威胁防护设置,并将

data
目录添加到排除项中。突然我的程序在所有目录中尖叫。

显然,Java 检查文件是否存在的方法(通过打开文件)与 Windows Defender 相结合,会减慢文件存在检查的速度!

(我刚刚通过删除 Windows Defender 排除来验证了这一点;当我在执行此操作后立即运行它时,循环突然停止了。)

这可不是什么好事。这根本不是什么好事。 Java 和 Windows Defender 似乎都没有做到理想的效果。

(我还注意到,第一次在目录中进行 Maven 构建时,重新启动后速度非常慢,直到我构建了一次项目。我想知道将项目目录添加到 Windows Defender 排除列表中是否会有帮助…)

正如 Luca Scarcia 所建议的那样,

File.exist()
使用了不同的技术,令人惊讶的是,即使没有 Windows Defender 排除,它似乎也能飞过所有目录。

为什么、为什么、为什么 Java 使用这种强力打开文件来检查 Java NIO 是否存在

Files.exists(Path)
?这是个问题。

© www.soinside.com 2019 - 2024. All rights reserved.