web-dev-qa-db-ja.com

Javaでファイルを一覧表示する最良の方法は、変更日でソートされていますか?

ディレクトリ内のファイルのリストを取得したいが、最も古いファイルが最初になるようにソートしたい。私の解決策は、File.listFilesを呼び出し、File.lastModifiedに基づいてリストを再ソートすることでしたが、もっと良い方法があるかどうか疑問に思いました。

編集:提案されているように、私の現在の解決策は、匿名のコンパレータを使用することです:

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());
    } });
225
cwick

あなたの解決策が唯一の賢明な方法だと思います。ファイルのリストを取得する唯一の方法は、 File.listFiles() を使用することです。ドキュメントには、ファイルの順序については保証しないと記載されています戻ってきた。したがって、 File.lastModified() を使用する Comparator を記述する必要がありますこれをファイルの配列とともに Arrays.sort() に渡します。

95
Dan Dyer

多数のファイルがある場合、これは高速になる可能性があります。これはdecorate-sort-undecorateパターンを使用するため、ソートアルゴリズムが2つのファイルを比較するたびにではなく、各ファイルの最終変更日がonceのみでフェッチされます。これにより、I/O呼び出しの数がO(n log n)からO(n)に減少する可能性があります。

ただし、コードの方が多いため、これは主に速度に関心があり、実際にはかなり高速な場合にのみ使用する必要があります(これは確認していません)。

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;
45
Jason Orendorff

同様のアプローチについてですが、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());
    }
});
33
PhannGor

Java 8以降のエレガントなソリューション:

File[] files = directory.listFiles();
Arrays.sort(files, Comparator.comparingLong(File::lastModified));

または、降順にしたい場合は、単に逆にしてください:

File[] files = directory.listFiles();
Arrays.sort(files, Comparator.comparingLong(File::lastModified).reversed());
28
Vini

Apache commons IO もご覧ください。組み込みの 最終変更コンパレータ と、ファイルを操作するためのその他多くのNiceユーティリティがあります。

25
user17163

Java 8の場合:

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

14
hasen

輸入:

org.Apache.commons.io.comparator.LastModifiedFileComparator

Apache Commons

コーデック:

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);

    }

ソートの実行中に、ソート中のファイルを変更または更新できる場合:


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

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;
}


これらのソリューションはどちらも、一時的なマップデータ構造を作成して、ディレクトリ内の各ファイルの最終更新日時を一定に節約します。これを行う必要があるのは、並べ替えの実行中にファイルが更新または変更されると、比較中に最終変更時刻が変更される可能性があるため、コンパレータがコンパレータインターフェイスの一般契約の推移性要件に違反するためです。

一方、並べ替え中にファイルが更新または変更されないことがわかっている場合は、この質問に対して送信された他のほとんどの回答を回避できます。

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

    Arrays.sort(dirListing, 0, dirListing.length);
    return dirListing;
}
2
Calvin Schultz
Collections.sort(listFiles, new Comparator<File>() {
        public int compare(File f1, File f2) {
            return Long.compare(f1.lastModified(), f2.lastModified());
        }
    });

listFilesは、ArrayList内のすべてのファイルのコレクションです

1
Anand Savjani

Apache LastModifiedFileComparator libraryを使用できます

 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 + "");
        }
1
Vikas
private static List<File> sortByLastModified(String dirPath) {
    List<File> files = listFilesRec(dirPath);
    Collections.sort(files, new Comparator<File>() {
        public int compare(File o1, File o2) {
            return Long.compare(o1.lastModified(), o2.lastModified());
        }
    });
    return files;
}
1
Jaydev

グアバを試すことができます 注文

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);
1

また、多数を処理しないため、さらに簡単になる可能性がある完全に異なる方法があります。

すべてのファイル名とlastModified日付を取得した後に配列全体をソートする代わりに、リストの正しい位置に取得した直後にすべてのファイル名を挿入できます。

次のようにできます:

list.add(1, object1)
list.add(2, object3)
list.add(2, object2)

Object2を位置2に追加すると、object3が位置3に移動します。

0
user4378029

追加のコンパレータなしで問題を処理する非常に簡単で便利な方法があります。変更された日付をファイル名とともに文字列にコーディングし、ソートして、後で再び削除します。

固定長20の文字列を使用し、それに変更日(長い)を入れて、先行ゼロで埋めます。次に、この文字列にファイル名を追加します。

String modified_20_digits = ("00000000000000000000".concat(Long.toString(temp.lastModified()))).substring(Long.toString(temp.lastModified()).length()); 

result_filenames.add(modified_20_digits+temp.getAbsoluteFile().toString());

ここで何が起こりますか:

Filename1:C:\ data\file1.html Last Modified:1532914451455 Last Modified 20 Digits:00000001532914451455

ファイル名1:C:\ data\file2.html最終更新日:1532918086822最終更新日20桁:00000001532918086822

filnamesを次のように変換します。

ファイル名1:00000001532914451455C:\ data\file1.html

ファイル名2:00000001532918086822C:\ data\file2.html

このリストを並べ替えることができます。

あとで再度20文字を削除するだけです(Java 8では、.replaceAll関数を使用して、1行だけで配列全体を削除できます)

0
user4378029

私は同じ問題を探していたときにAndroidでこの投稿に来ました。これが最終更新日でソートされたファイルを取得する最良の方法であるとは言いませんが、私がまだ見つけた最も簡単な方法です。

以下のコードは誰かに役立つかもしれません-

File downloadDir = new File("mypath");    
File[] list = downloadDir.listFiles();
    for (int i = list.length-1; i >=0 ; i--) {
        //use list.getName to get the name of the file
    }

ありがとう

0
ezcodr