Il modo migliore per elencare i file in Java, ordinati per data modificata?

Voglio ottenere un elenco di file in una directory, ma voglio ordinarlo in modo che i file più vecchi siano i primi. La mia soluzione era chiamare File.listFiles e ricorrere semplicemente all’elenco basato su File.lastModified, ma mi chiedevo se ci fosse un modo migliore.

Modifica: la mia soluzione attuale, come suggerito, è quella di utilizzare un comparatore anonimo:

File[] files = directory.listFiles(); Arrays.sort(files, new Comparator(){ public int compare(File f1, File f2) { return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); } }); 

Penso che la tua soluzione sia l’unica strada sensata. L’unico modo per ottenere l’elenco dei file è utilizzare File.listFiles () e la documentazione afferma che ciò non garantisce l’ordine dei file restituiti. Pertanto è necessario scrivere un comparatore che utilizza File.lastModified () e passare questo, insieme alla matrice di file, in Arrays.sort () .

Questo potrebbe essere più veloce se hai molti file. Ciò utilizza il pattern decora-ordinamento-decoro in modo che la data dell’ultima modifica di ogni file venga recuperata una sola volta invece che ogni volta che l’algoritmo di ordinamento confronta due file. Questo potenzialmente riduce il numero di chiamate I / O da O (n log n) a O (n).

È più codice, però, quindi dovrebbe essere usato solo se si è principalmente interessati alla velocità ed è misurabilmente più veloce nella pratica (che non ho controllato).

 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; 

Che cosa è un approccio simile, ma senza boxe per gli oggetti Long:

 File[] files = directory.listFiles(); Arrays.sort(files, new Comparator() { public int compare(File f1, File f2) { return Long.compare(f1.lastModified(), f2.lastModified()); } }); 

Si potrebbe anche guardare l’ IO commons di apache , ha un comparatore di ultima modifica e molte altre utili utility per lavorare con i file.

Soluzione elegante con Java 8:

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

Oppure, se lo vuoi in ordine decrescente, basta invertirlo:

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

In Java 8:

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

Importazioni:

 org.apache.commons.io.comparator.LastModifiedFileComparator 

Apache Commons

Codice :

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

Se i file che si stanno ordinando vengono modificati / aggiornati mentre viene eseguito l’ordinamento, si violerà il requisito di transitività del contratto generale del comparatore. Per evitare questo potenziale bug, ti consigliamo di creare una tabella di ricerca statica degli ultimi valori modificati da utilizzare nel comparatore per ogni file, qualcosa di simile al seguente:

  Collection files = ... final Map staticLastModifiedTimes = new HashMap(); for(final File f : files) { staticLastModifiedTimes.put(f, f.lastModified()); } Collections.sort(files, new Comparator() { @Override public int compare(final File f1, final File f2) { return staticLastModifiedTimes.get(f1).compareTo(staticLastModifiedTimes.get(f2)); } }); 
 public String[] getDirectoryList(String path) { String[] dirListing = null; File dir = new File(path); dirListing = dir.list(); Arrays.sort(dirListing, 0, dirListing.length); return dirListing; } 

Puoi provare guava Ordinare :

 Function getLastModified = new Function() { public Long apply(File file) { return file.lastModified(); } }; List orderedFiles = Ordering.natural().onResultOf(getLastModified). sortedCopy(files); 

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

Sono venuto a questo post quando stavo cercando lo stesso problema ma in android . Non dico che questo sia il modo migliore per ottenere i file ordinati in base alla data dell’ultima modifica, ma è il modo più semplice che ho trovato finora.

Sotto il codice potrebbe essere utile a qualcuno-

 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 } 

Grazie

 Collections.sort(listFiles, new Comparator() { public int compare(File f1, File f2) { return Long.compare(f1.lastModified(), f2.lastModified()); } }); 

dove listFiles è la raccolta di tutti i file in ArrayList

C’è anche un modo completamente diverso che potrebbe essere ancora più semplice, dato che non ci occupiamo di grandi numeri.

Invece di ordinare l’intero array dopo aver recuperato tutti i nomi di file e le date LastModified, è sufficiente inserire ogni singolo nome di file solo dopo averlo recuperato nella giusta posizione dell’elenco.

Puoi farlo in questo modo:

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

Dopo aver aggiunto l’object 2 alla posizione 2, sposta l’object 3 nella posizione 3.

C’è un modo molto semplice e conveniente per gestire il problema senza alcun comparatore extra. Basta codificare la data modificata nella stringa con il nome del file, ordinarla e poi rimuoverla di nuovo.

Usa una stringa di lunghezza fissa 20, inserisci la data modificata (lunga) e completa gli zero iniziali. Quindi aggiungi il nome del file a questa stringa:

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

Quello che succede è questo qui:

Nome file1: C: \ data \ file1.html Ultima modifica: 1532914451455 20 cifre dell’ultima modifica: 00000001532914451455

Nome file1: C: \ data \ file2.html Ultima modifica: 1532918086822 20 cifre dell’ultima modifica: 00000001532918086822

trasforma i nomi dei file in:

Nome file1: 00000001532914451455C: \ data \ file1.html

Nome file2: 00000001532918086822C: \ data \ file2.html

È quindi ansible ordinare questa lista.

Tutto quello che devi fare è rimuovere nuovamente i 20 caratteri in un secondo momento (in Java 8, puoi eliminarli per l’intero array con una sola riga usando la funzione .replaceAll)