Frage

Ich mag eine Liste von Dateien in einem Verzeichnis bekommen, aber ich will es so sortieren, dass die ältesten Dateien zuerst. Meine Lösung war File.listFiles zu nennen und greift nur die Liste basierend auf File.lastModified, aber ich frage mich, ob es ein besserer Weg war.

Edit: Meine aktuelle Lösung, wie vorgeschlagen, ist einen anonymen Vergleicher zu verwenden:

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());
    } });
War es hilfreich?

Lösung

Ich denke, Ihre Lösung der einzig vernünftige Weg ist. Die einzige Möglichkeit, die Liste der Dateien zu erhalten, ist File.listFiles () und die Dokumentation besagt, dass dies keine Garantien über die Reihenfolge der Dateien zurück macht. Daher benötigen Sie einen Vergleicher schreiben dass Verwendungen File.lastModified () und übergeben Sie diese zusammen mit der Anordnung von Dateien, auf Arrays.sort () .

Andere Tipps

Dies könnte schneller sein, wenn Sie viele Dateien haben. Dies verwendet die deco-Art-undecorate Muster, so dass das Datum der letzten Änderung jeder Datei nur geholt wird einmal , anstatt jedes Mal, wenn der Sortieralgorithmus zwei Dateien vergleicht. Dadurch verringert sich möglicherweise die Anzahl der I / O-Anrufe von O (n log n) bis O (n).

Es ist mehr Code, obwohl, so dass diese nur verwendet werden sollen, wenn Sie Geschwindigkeit in erster Linie betroffen sind, und es ist messbar schneller in der Praxis (was ich nicht überprüft haben).

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;

Was ist mit ähnlichem Ansatz, aber ohne Boxen auf die Lange Objekte:

File[] files = directory.listFiles();

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

Elegante Lösung, da Java 8:

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

Oder, wenn Sie es in absteigender Reihenfolge wollen, nur umgekehrt vor:

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

Sie auch unter Apache Commons IO es einen eingebauten zuletzt Komparator und viele andere nette Dienstprogramme für die Arbeit mit Dateien.

In Java 8:

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

Importe:

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

    }

Wenn die Dateien Sie sortieren können zur gleichen Zeit geändert oder aktualisiert werden, die Art durchgeführt wird:


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


Beiden Lösungen erstellen Sie eine temporäre Karte Datenstruktur auf eine konstante Zeit die letzte Änderung für jede Datei im Verzeichnis speichert aus. Der Grund, warum wir dies tun müssen, ist, dass, wenn Ihre Dateien aktualisiert werden oder geändert, während der Art dann ausgeführt wird Ihr Komparator wird die Transitivität Anforderung der Komparator-Schnittstelle der allgemeinen Vertrages verletzt, weil die letzten modifizierten Zeiten während des Vergleichs zu ändern können.

Wenn auf der anderen Seite wissen Sie die Dateien nicht während Ihrer Art aktualisiert oder geändert werden, können Sie mit so ziemlich jeder anderen Antwort erhalten weg auf diese Frage gestellt.

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

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

Sie können versuchen, Guave Reihenfolge

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

Sie können Apache verwenden LastModifiedFileComparator Bibliothek

 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 + "");
        }
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;
}
Collections.sort(listFiles, new Comparator<File>() {
        public int compare(File f1, File f2) {
            return Long.compare(f1.lastModified(), f2.lastModified());
        }
    });

Dabei gilt listFiles die Sammlung aller Dateien in Arraylist ist

Ich kam zu diesem Beitrag, als ich für das gleiche Problem gesucht, aber in android. Ich sage nicht, das ist die beste Art und Weise sortieren Dateien nach Datum der letzten Änderung zu bekommen, aber es ist der einfachste Weg, fand ich noch.

Im Folgenden Code kann jemand hilfreich sein -

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
    }

Danke

Es gibt eine sehr einfache und bequeme Möglichkeit, das Problem ohne zusätzlichen Komparator zu handhaben. Code nur das Änderungsdatum in den String mit dem Dateinamen, sortieren, und es später wieder abzustreifen.

einen String mit fester Länge 20, legt das Änderungsdatum (long) hinein und füllen sich mit führenden Nullen. Dann hängen Sie einfach die Dateinamen auf diese Zeichenfolge:

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

Was passiert, ist dies hier:

Filename1: C: \ data \ file1.html Zuletzt geändert: 1532914451455 zuletzt aktualisiert 20 Ziffern: 00000001532914451455

Filename1: C: \ data \ file2.html Zuletzt geändert: 1532918086822 zuletzt aktualisiert 20 Ziffern: 00000001532918086822

transformiert filnames zu:

Filename1: 00000001532914451455C: \ data \ file1.html

Filename2: 00000001532918086822C: \ data \ file2.html

Sie können dann sortieren gerade diese Liste.

Alles, was Sie tun müssen, ist die 20 Zeichen später wieder abzustreifen (in Java 8, können Sie es für das gesamte Array mit einer gerade Linie Streifen der .ReplaceAll Funktion)

Es gibt auch eine ganz andere Art und Weise, die noch einfacher sein kann, da wir nicht mit großen Zahlen umgehen.

Statt das gesamte Array Sortierung, nachdem Sie alle Dateinamen abgerufen und lastModified Daten, können Sie einfach jeden einzelnen Dateinamen einfügen, kurz nachdem Sie es an der richtigen Stelle der Liste abgerufen werden.

Sie können es tun, wie folgt:

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

Nachdem Sie hinzufügen object2 auf Position 2, wird es bewegen Objekt3 3. zu positionieren

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top