有没有比File.listFiles()方法更好的替代方案?

时间:2018-04-29 14:59:21

标签: java performance file io

我需要读取绝对路径,文件名和&目录中文件的大小。 这就是我目前的做法:

File diretory = <dir_path>;
File[] listFiles = directory.listFiles();
for (int i = 0; i < listFiles.length; i++) {
    String fileName = file.getName();
    String filePath = file.getAbsolutePath();
    long fileLen = file.length();
    long filelastModified = file.getLastModified();
    ...
}

我的目录中可以包含1000个文件。由于I / O操作非常昂贵,这是完成我正在做的事情的最佳方式吗?

5 个答案:

答案 0 :(得分:2)

使用Java 7,java.nio.file.DirectoryStream<Path>提供了一种可以获得巨大性能提升的替代方案。

import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
...
    private static void nioDir( String filePath, int maxFiles )
       throws IOException {
      int i = 1;
      Path dir = FileSystems.getDefault().getPath( filePath );
      DirectoryStream<Path> stream = Files.newDirectoryStream( dir );
      for (Path path : stream) {
        System.out.println( "" + i + ": " + path.getFileName() );
        if (++i > maxFiles) break;
      }
      stream.close();
    }

答案 1 :(得分:1)

AFAIK,这在Java中尽可能高效。你可能能够挤出2到5%,但这通常不是那种值得提升的性能。

问题在于,典型的操作系统不提供一次检索多个文件的元数据或一次检索多个元数据值的方法。

我希望元数据操作(length()getLastModified()等)绝大多数时间都会使用。但是值得对您的应用程序进行分析以验证它。

说完这个之后,你的应用程序的I / O可能没有你想象的那么慢。 OS可能会读取并缓存包含元数据的磁盘块。读取文件元数据的系统调用将在大多数时间返回缓存信息。 (当然,这是特定于操作系统的,并且取决于您使用的文件系统的类型。)

答案 2 :(得分:1)

在你的情况下:

meta.error

将创建1000个File[] listFiles = directory.listFiles(); 个对象,但这些不是昂贵的I / O操作,因为File在创建new File()对象时不执行IO操作。 但请注意,您可以同时避免一次创建所有Files对象,并通过流式传输文件来减少消耗的内存  返回FileInputStream的{​​{3}}和返回DirectoryStream<Path>的{​​{3}}提供了实现此目的的方法。
Files.newDirectoryStream(Path dir)一篇帖子指出了它们之间的一些差异。

因此,您可以通过这种方式使用Stream<Path> API获得相同的结果:

java.nio

编辑评论:

  

如果有子目录&amp;需要检索   子目录中的文件细节呢?

在这种情况下Path directory = ...; Files.newDirectoryStream(directory) .forEach(p -> { try { String fileName = p.getFileName().toString(); String filePath = p.toAbsolutePath().toString(); long fileLen = Files.size(p); long filelastModified = Files.getLastModifiedTime(p).toMillis(); } catch (IOException e) { // FIXME to handle } }); 更适合,因为它是递归的 它非常接近:

Files.walk()

答案 3 :(得分:1)

我使用File.list(),而不是listFiles(),它更接近本机api,更少的File对象可以预先创建。但这是一个很小的收获。

注意File.list()仅返回子名称这一事实更有意思,因此您可以保存一些getter,并且给定父级的所有子级的路径都相同,从而再次保存更多琐碎的getter

你不会保存大小和日期,必须为每个人调用一次,抱歉。

答案 4 :(得分:0)

我从存储中加载一大堆文件时遇到了类似的问题,经过数小时的调整后得出结论。

使用 File.list() 获取文件名并手动附加它们的目录路径。

并在需要时创建 File() 元素