在 Java 中列出文件的最佳方法,按修改日期排序?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/203030/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 11:19:21  来源:igfitidea点击:

Best way to list files in Java, sorted by Date Modified?

javafilesorting

提问by cwick

I want to get a list of files in a directory, but I want to sort it such that the oldest files are first. My solution was to call File.listFiles and just resort the list based on File.lastModified, but I was wondering if there was a better way.

我想获取目录中的文件列表,但我想对其进行排序,以便最旧的文件排在最前面。我的解决方案是调用 File.listFiles 并根据 File.lastModified 重新使用列表,但我想知道是否有更好的方法。

Edit: My current solution, as suggested, is to use an anonymous Comparator:

编辑:按照建议,我目前的解决方案是使用匿名比较器:

File[] files = directory.listFiles();

Arrays.sort(files, new Comparator<File>(){
    public int compare(File f1, File f2)
    {
        return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified());
    } });

采纳答案by Dan Dyer

I think your solution is the only sensible way. The only way to get the list of files is to use File.listFiles()and the documentation states that this makes no guarantees about the order of the files returned. Therefore you need to write a Comparatorthat uses File.lastModified()and pass this, along with the array of files, to Arrays.sort().

我认为您的解决方案是唯一明智的方法。获取文件列表的唯一方法是使用File.listFiles()并且文档指出这不能保证返回文件的顺序。因此,您需要编写一个使用File.lastModified()Comparator并将其与文件数组一起传递给Arrays.sort()

回答by user17163

You might also look at apache commons IO, it has a built in last modified comparatorand many other nice utilities for working with files.

您还可以查看apache commons IO,它有一个内置的最后修改的比较器和许多其他用于处理文件的不错的实用程序。

回答by Jason Orendorff

This might be faster if you have many files. This uses the decorate-sort-undecorate pattern so that the last-modified date of each file is fetched only oncerather than every time the sort algorithm compares two files. This potentially reduces the number of I/O calls from O(n log n) to O(n).

如果您有很多文件,这可能会更快。这使用了装饰-排序-取消装饰模式,因此每个文件的最后修改日期只提取一次,而不是每次排序算法比较两个文件时。这可能会将 I/O 调用的数量从 O(n log n) 减少到 O(n)。

It's more code, though, so this should only be used if you're mainly concerned with speed and it is measurably faster in practice (which I haven't checked).

但是,这是更多的代码,因此只有在您主要关注速度并且在实践中它明显更快(我没有检查过)时才应该使用它。

class Pair implements Comparable {
    public long t;
    public File f;

    public Pair(File file) {
        f = file;
        t = file.lastModified();
    }

    public int compareTo(Object o) {
        long u = ((Pair) o).t;
        return t < u ? -1 : t == u ? 0 : 1;
    }
};

// Obtain the array of (file, timestamp) pairs.
File[] files = directory.listFiles();
Pair[] pairs = new Pair[files.length];
for (int i = 0; i < files.length; i++)
    pairs[i] = new Pair(files[i]);

// Sort them by timestamp.
Arrays.sort(pairs);

// Take the sorted pairs and extract only the file part, discarding the timestamp.
for (int i = 0; i < files.length; i++)
    files[i] = pairs[i].f;

回答by Calvin Schultz

public String[] getDirectoryList(String path) {
    String[] dirListing = null;
    File dir = new File(path);
    dirListing = dir.list();

    Arrays.sort(dirListing, 0, dirListing.length);
    return dirListing;
}

回答by Vitalii Fedorenko

You can try guava Ordering:

您可以尝试番石榴订购

Function<File, Long> getLastModified = new Function<File, Long>() {
    public Long apply(File file) {
        return file.lastModified();
    }
};

List<File> orderedFiles = Ordering.natural().onResultOf(getLastModified).
                          sortedCopy(files);

回答by Matthew Madson

If the files you are sorting can be modified or updated at the same time the sort is being performed:

如果您正在排序的文件可以在执行排序的同时修改或更新:



Java 8+

Java 8+

private static List<Path> listFilesOldestFirst(final String directoryPath) throws IOException {
    try (final Stream<Path> fileStream = Files.list(Paths.get(directoryPath))) {
        return fileStream
            .map(Path::toFile)
            .collect(Collectors.toMap(Function.identity(), File::lastModified))
            .entrySet()
            .stream()
            .sorted(Map.Entry.comparingByValue())
//            .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))  // replace the previous line with this line if you would prefer files listed newest first
            .map(Map.Entry::getKey)
            .map(File::toPath)  // remove this line if you would rather work with a List<File> instead of List<Path>
            .collect(Collectors.toList());
    }
}

Java 7

爪哇 7

private static List<File> listFilesOldestFirst(final String directoryPath) throws IOException {
    final List<File> files = Arrays.asList(new File(directoryPath).listFiles());
    final Map<File, Long> constantLastModifiedTimes = new HashMap<File,Long>();
    for (final File f : files) {
        constantLastModifiedTimes.put(f, f.lastModified());
    }
    Collections.sort(files, new Comparator<File>() {
        @Override
        public int compare(final File f1, final File f2) {
            return constantLastModifiedTimes.get(f1).compareTo(constantLastModifiedTimes.get(f2));
        }
    });
    return files;
}


Both of these solutions create a temporary map data structure to save off a constant last modified time for each file in the directory. The reason we need to do this is that if your files are being updated or modified while your sort is being performed then your comparator will be violating the transitivity requirement of the comparator interface's general contract because the last modified times may be changing during the comparison.


这两种解决方案都创建了一个临时映射数据结构,以节省目录中每个文件的恒定上次修改时间。我们需要这样做的原因是,如果您的文件在执行排序时被更新或修改,那么您的比较器将违反比较器接口的一般合同的传递性要求,因为上次修改时间可能会在比较期间发生变化。

If, on the other hand, you know the files will not be updated or modified during your sort, you can get away with pretty much any other answer submitted to this question, of which I'm partial to:

另一方面,如果您知道在排序期间不会更新或修改文件,则您可以使用提交给此问题的几乎任何其他答案,其中我偏爱:

Java 8+ (No concurrent modifications during sort)

Java 8+(排序期间无并发修改)

private static List<Path> listFilesOldestFirst(final String directoryPath) throws IOException {
    try (final Stream<Path> fileStream = Files.list(Paths.get(directoryPath))) {
        return fileStream
            .map(Path::toFile)
            .sorted(Comparator.comparing(File::lastModified))
            .map(File::toPath)  // remove this line if you would rather work with a List<File> instead of List<Path>
            .collect(Collectors.toList());
    }
}

Note: I know you can avoid the translation to and from File objects in the above example by using Files::getLastModifiedTimeapi in the sorted stream operation, however, then you need to deal with checked IO exceptions inside your lambda which is always a pain. I'd say if performance is critical enough that the translation is unacceptable then I'd either deal with the checked IOException in the lambda by propagating it as an UncheckedIOException or I'd forego the Files api altogether and deal only with File objects:

注意:我知道您可以通过在排序流操作中使用Files::getLastModifiedTimeapi来避免上例中 File 对象的转换,但是,您需要处理 lambda 中的已检查 IO 异常,这总是很痛苦. 我会说,如果性能足够关键以至于翻译是不可接受的,那么我要么通过将其作为 UncheckedIOException 传播来处理 lambda 中已检查的 IOException,要么我会完全放弃 Files api 并仅处理 File 对象:

final List<File> sorted = Arrays.asList(new File(directoryPathString).listFiles());
sorted.sort(Comparator.comparing(File::lastModified));

回答by PhannGor

What's about similar approach, but without boxing to the Long objects:

类似的方法是什么,但没有对 Long 对象进行装箱:

File[] files = directory.listFiles();

Arrays.sort(files, new Comparator<File>() {
    public int compare(File f1, File f2) {
        return Long.compare(f1.lastModified(), f2.lastModified());
    }
});

回答by Vikas

You can use Apache LastModifiedFileComparatorlibrary

您可以使用 Apache LastModifiedFileComparator

 import org.apache.commons.io.comparator.LastModifiedFileComparator;  


File[] files = directory.listFiles();
        Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_COMPARATOR);
        for (File file : files) {
            Date lastMod = new Date(file.lastModified());
            System.out.println("File: " + file.getName() + ", Date: " + lastMod + "");
        }

回答by Balaji Boggaram Ramanarayan

Imports :

进口:

org.apache.commons.io.comparator.LastModifiedFileComparator

Apache Commons

阿帕奇公地

Code :

代码 :

public static void main(String[] args) throws IOException {
        File directory = new File(".");
        // get just files, not directories
        File[] files = directory.listFiles((FileFilter) FileFileFilter.FILE);

        System.out.println("Default order");
        displayFiles(files);

        Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_COMPARATOR);
        System.out.println("\nLast Modified Ascending Order (LASTMODIFIED_COMPARATOR)");
        displayFiles(files);

        Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_REVERSE);
        System.out.println("\nLast Modified Descending Order (LASTMODIFIED_REVERSE)");
        displayFiles(files);

    }

回答by hasen

In Java 8:

在 Java 8 中:

Arrays.sort(files, (a, b) -> Long.compare(a.lastModified(), b.lastModified()));

Arrays.sort(files, (a, b) -> Long.compare(a.lastModified(), b.lastModified()));