我想知道File.exists()
是如何运作的。我不太清楚文件系统是如何工作的,所以我应该先开始在那里阅读。
但是要获得快速的预先信息:
如果在某个期刊中注册了该路径和文件名,那么是对File.exists()
调用文件系统的单个操作吗?或者操作系统是否获取目录的内容,然后通过它扫描匹配?
我认为这将取决于文件系统,但也许所有文件系统都使用快速方法?
我不是在谈论网络和磁带系统。让它保持ntfs,extX,zfs,jfs: - )
答案 0 :(得分:16)
测量必要的时间并看看自己。正如你所说,绝对依赖于文件系统。
long t1 = System.currentTimeMillis();
...Your File.exists call
long t2 = System.currentTimeMillis();
System.out.println("time: " + (t2 - t1) + " ms");
您将看到它总会给您不同的结果,因为它还取决于您的操作系统缓存数据的方式,负载等。
答案 1 :(得分:15)
如果第一次执行此操作完全取决于文件系统。这是由操作系统完成的,Java并没有发挥任何作用。
就性能而言,在所有情况下都需要读取磁盘。这通常需要8-12毫秒。 @Sven指出一些存储可能会变慢,但在性能很重要的情况下这种情况相对较少。如果这是一个网络文件系统,您可能会有额外的延迟(通常相对较小,但这取决于您的网络延迟)。
相比之下,OS和Java所做的其他事情都非常短暂。
但是,如果检查文件是否重复存在,则可能不需要磁盘访问,因为信息可以缓存,在这种情况下是操作系统占用的时间和资源。 File.exists()创建的对象中最大的一个(您不会认为它会)但是它会在每次调用时编码文件的名称,从而创建大量对象。如果将File.exists()置于紧密循环中,则每秒可以创建400MB的垃圾。 :(
日记文件系统通过跟踪您对文件系统所做的所有更改来以不同方式工作,但它们不会更改您读取文件系统的方式。
答案 2 :(得分:8)
大多数与文件相关的操作都不是用Java执行的;存在执行这些活动的本机代码。实际上,完成的大部分工作取决于FileSystem
对象(支持File
对象)的性质以及操作系统中本机IO操作的底层实现。
为了清楚起见,我将在OpenJDK 6中介绍实现的情况。 File.exists()实现将实际检查推迟到FileSystem类:
public boolean exists() {
... calls to SecurityManager have been omitted for brevity ...
return ((fs.getBooleanAttributes(this) & FileSystem.BA_EXISTS) != 0);
}
FileSystem类是抽象的,并且存在所有支持的文件系统的实现:
package java.io;
/**
* Package-private abstract class for the local filesystem abstraction.
*/
abstract class FileSystem
注意包的私有性。 Java Runtime Environment将提供扩展FileSystem类的具体类。在OpenJDK实现中,有:
对于getBooleanAttributes
方法,所有上述类都委托给本机代码。这意味着在这种情况下,性能不受托管(Java)代码的约束;文件系统的实现,以及正在进行的本机调用的性质对性能的影响更大。
更新#2
基于更新的问题 -
嗯,那还不重要。不同的操作系统将以不同的方式实现对不同文件系统的支持。例如,Windows中的NTFS支持将与* nix中的支持不同,因为除了通过驱动程序与设备通信之外,操作系统还必须执行簿记共享;并非所有工作都在设备中完成。我不是在谈论网络和磁带系统。让它保持ntfs,extX,zfs,jfs
在Windows中,您几乎总能找到file system filter drivers的概念来管理与其他文件系统筛选器驱动程序或文件系统通信的任务。这对于支持各种操作是必要的;一个例子是使用过滤驱动程序用于反病毒引擎和其他软件(即时加密和压缩产品)拦截IO调用。
在* nix中,您将进行stat()系统调用,该调用将执行读取文件描述符的inode信息的必要活动。
答案 3 :(得分:0)
它在任何现代机器上都非常快,我的测试显示,我的2013 Mac w / SSD上有0.0028毫秒(2.8微秒)
以307毫秒创建1,000个文件,每个文件0.0307毫秒
1,000个.exists()以28毫秒为单位,每个文件0.0028毫秒
这是Groovy(Java)中的测试
def index() {
File fileWrite
long start = System.currentTimeMillis()
(1..1000).each {
fileWrite = new File("/tmp/fileSpeedTest/${it}.txt")
fileWrite.write('Some nice text')
}
long diff = System.currentTimeMillis() - start
println "1,000 files created in $diff millis, ${diff/10000.0} millis per file"
start = System.currentTimeMillis()
(1..1000).each {
fileWrite = new File("/tmp/fileSpeedTest/${it}.txt")
if ( ! fileWrite.exists() )
throw new Exception("where's the file")
}
diff = System.currentTimeMillis() - start
println "1,000 .exists() done in $diff millis, ${diff/10000.0} millis per file"
}