如何在不创建对象的情况下找出java中文件和目录的大小?

时间:2011-05-02 12:37:26

标签: java filesize

首先请不要忽视,因为您可能认为这是常见问题,但事实并非如此。我知道如何使用file.lengthApache FileUtils.sizeOfDirectory找出文件和目录的大小。

我的问题是,在我的情况下文件和目录大小太大(数百mb)。当我尝试使用上面的代码找出大小(例如创建文件对象)时,我的程序变得非常耗费资源并降低性能。

有没有办法知道文件的大小而不创建对象?

我正在使用 对于文件文件file1 =新文件(fileName); long size = file1.length();

和目录,文件dir1 =新文件(dirPath); long size = fileUtils.sizeOfDirectiry(dir1);

我有一个参数可以进行大小计算。如果参数为假,那么它会顺利进行。如果为false则程序滞后或挂起..我正在计算4个目录和2个数据库文件的大小。

6 个答案:

答案 0 :(得分:4)

文件对象非常轻量级。您的代码有问题,或问题不在于文件对象,而在于获取文件大小所需的高清访问权限。如果你为一个大的数字的文件(比如成千上万)这样做,那么硬盘会做很多寻求,这几乎是现代PC上最慢的操作(由几个数量级)。

答案 1 :(得分:3)

文件只是文件路径的包装器。文件只有文件名的大小并不重要。

如果要获取目录中所有文件的大小,操作系统需要读取目录,然后查找每个文件以获取其大小。每次访问大约需要10毫秒(因为这是硬盘驱动器的典型搜索时间)因此,如果您有100,000个文件,则需要大约17分钟才能获得所有大小。

加快这一速度的唯一方法是获得更快的驱动器。例如固态硬盘的平均搜索时间为0.1毫秒,但仍需要10秒或更长时间才能获得100K文件的大小。

BTW:每个文件的大小无关紧要,因为它实际上并没有读取文件。只有文件条目的大小。


编辑:例如,如果我尝试获取大目录的大小。一旦数据被缓存,它起初很慢但速度要快得多。

$ time du -s /usr
2911000 /usr

real    0m33.532s
user    0m0.880s
sys 0m5.190s

$ time du -s /usr
2911000 /usr

real    0m1.181s
user    0m0.300s
sys 0m0.840s

$ find /usr | wc -l
259934

首先查找速度如此之快的原因是文件全部安装在一起,并且大部分信息在磁盘上连续可用。一旦信息在内存中,就很快就会读取文件信息。

计时FileUtils.sizeOfDirectory(“/ usr”)需要8.7秒。与du所花费的时间相比,这相对较慢,但它每秒处理大约30K个文件。

更改可能是运行Runtime.exec("du -s "+directory);但是,这最多只能产生几秒钟的差异。如果磁盘不在缓存中,大部分时间都可能花在等待磁盘上。

答案 2 :(得分:2)

我们在File.listFiles()上遇到与大量文件相似的性能问题。

我们的设置是一个包含10个子文件夹的文件夹,每个文件夹包含10,000个文件。 该文件夹位于网络共享上,而不是运行测试的计算机上。

我们使用FileFilter只接受具有已知扩展名的文件或目录,以便我们可以在目录中使用。

分析显示,大约70%的时间花在调用File.isDirectory(我假设Apache正在调用)上。每个文件都有两个isDirectory调用(一个在过滤器中,一个在文件处理阶段)。

File.isDirectory很慢,因为它必须为每个文件点击网络共享。

在有效目录节省了大量时间之前,反转过滤器中的检查顺序以检查有效名称,但我们仍然需要调用isDirectory进行递归查找。

我的解决方案是在本机代码中实现listFiles的一个版本,它将返回一个数据结构,其中包含有关文件的所有元数据,而不仅仅是像File那样的文件名。

这解决了性能问题,但增加了一个维护问题,即必须由Java开发人员维护本机代码(幸运的是我们只支持一个操作系统)。

答案 3 :(得分:1)

我认为您需要阅读文件的元数据。 阅读本教程以获取更多信息。这可能是您正在寻找的解决方案: http://download.oracle.com/javase/tutorial/essential/io/fileAttr.html

答案 4 :(得分:1)

回答我自己的问题..

这不是最好的解决方案,但适用于我的情况..

我创建了一个批处理脚本来获取目录的大小,然后在java程序中读取它。当目录中的文件数超过1L时(这总是在我的情况下),它给我减少执行时间.sizeOfDirectory大约需要30255毫秒,使用批处理脚本我得到1700毫秒..对于较少数量的文件,批处理脚本是昂贵的

答案 5 :(得分:0)

我将添加Peter Lawrey的回答,并补充说当一个目录里面有很多文件(直接,而不是在子目录中) - file.listFiles()所需的时间非常慢(我不喜欢没有确切的数字,我从经验中知道。如果我没记错的话,文件的数量必须很大,数千个 - 如果这是你的情况,那么fileUtils将会尝试将所有名称一次加载到内存中 - 这可能会消耗掉。

如果这是你的情况 - 我建议重组目录,使其具有某种层次结构,以确保每个子目录中的少量文件。