Java 是否有更好的方法替代File.listFiles()方法?

Java 是否有更好的方法替代File.listFiles()方法?,java,performance,file,io,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(); lon

我需要读取目录中文件的绝对路径、文件名和大小。 我现在就是这样做的:

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();
    ...
}
文件目录=;
File[]listFiles=directory.listFiles();
对于(int i=0;i

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

AFAIK,这在Java中几乎是尽可能高效的。您可能可以压缩2%到5%,但这通常不是值得改进的性能

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

我希望元数据操作(
length()
getLastModified()
等等)将占用绝大多数时间。但值得分析您的应用程序以验证这一点


话虽如此,您的应用程序的I/O可能没有您想象的那么慢。操作系统可能会读取并缓存包含元数据的磁盘块。读取文件元数据的系统调用大部分时间都将返回缓存信息。(当然,这是特定于操作系统的,取决于您使用的文件系统的类型。)

AFAIK,这在Java中几乎是尽可能高效的。您可能可以压缩2%到5%,但这通常不是值得改进的性能

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

我希望元数据操作(
length()
getLastModified()
等等)将占用绝大多数时间。但值得分析您的应用程序以验证这一点

话虽如此,您的应用程序的I/O可能没有您想象的那么慢。操作系统可能会读取并缓存包含元数据的磁盘块。读取文件元数据的系统调用大部分时间都将返回缓存信息。(当然,这是特定于操作系统的,取决于您使用的文件系统类型。)

在您的情况下:

File[] listFiles = directory.listFiles();
将创建1000个
文件
对象,但这些不是昂贵的I/O操作,因为
新建文件()
在创建对象时不会执行IO操作,而
文件输入流
会执行。
但请注意,您仍然可以避免一次创建所有文件对象,并通过对漫游文件进行流式处理来减少消耗的内存。
返回
目录流
和返回
的方法提供了实现此目的的方法。
指出他们之间一些差异的帖子

因此,您可以通过以下方式使用
java.nio
API获得相同的结果:

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()更合适,因为它是递归的。
它非常接近:

Path directory = ...;
Files.walk(directory)
     .forEach(p -> {
         try {
                // same code ....
         } catch (IOException e) {
             // FIXME to handle
         }

     });
就你而言:

File[] listFiles = directory.listFiles();
将创建1000个
文件
对象,但这些不是昂贵的I/O操作,因为
新建文件()
在创建对象时不会执行IO操作,而
文件输入流
会执行。
但请注意,您仍然可以避免一次创建所有文件对象,并通过对漫游文件进行流式处理来减少消耗的内存。
返回
目录流
和返回
的方法提供了实现此目的的方法。
指出他们之间一些差异的帖子

因此,您可以通过以下方式使用
java.nio
API获得相同的结果:

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()更合适,因为它是递归的。
它非常接近:

Path directory = ...;
Files.walk(directory)
     .forEach(p -> {
         try {
                // same code ....
         } catch (IOException e) {
             // FIXME to handle
         }

     });
我会使用File.list(),而不是listFiles(),它更接近本机api,前期创建的文件对象更少。但这只是一个小小的收获

更有趣的是,注意File.list()只返回子名称,因此您保存了几个getter,并且给定父级的所有子级的路径都相同,再次保存了更多琐碎的getter

您不会保存大小和日期,它们必须每个调用一次,抱歉。

我会使用File.list(),而不是listFiles(),它更接近本机api,前期创建的文件对象更少。但这只是一个小小的收获

更有趣的是,注意File.list()只返回子名称,因此您保存了几个getter,并且给定父级的所有子级的路径都相同,再次保存了更多琐碎的getter


您不会在大小和日期上进行保存,很抱歉,它们必须一次调用一次。

对于Java 7,
Java.nio.file.DirectoryStream
提供了一种性能上获得巨大提升的替代方案

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();
    }
import java.io.IOException;
导入java.nio.file.DirectoryStream;
导入java.nio.file.FileSystems;
导入java.nio.file.Files;
导入java.nio.file.Path;
...
私有静态void nioDir(字符串文件路径,int-maxFiles)
抛出IOException{
int i=1;
Path dir=FileSystems.getDefault().getPath(filePath);
DirectoryStream=Files.newDirectoryStream(dir);
用于(路径:流){
System.out.println(“+i+”:“+path.getFileName());
如果(++i>maxFiles)中断;
}
stream.close();
}

对于Java7,
Java.nio.file.DirectoryStream
提供了