Le meilleur moyen de répertorier les fichiers en Java, triés par date de modification?

StackOverflow https://stackoverflow.com/questions/203030

  •  03-07-2019
  •  | 
  •  

Question

Je souhaite obtenir une liste de fichiers dans un répertoire, mais je souhaite le trier de manière à ce que les fichiers les plus anciens apparaissent en premier. Ma solution consistait à appeler File.listFiles et à utiliser la liste basée sur File.lastModified, mais je me demandais s'il existait un meilleur moyen.

Modifier: ma solution actuelle, comme suggéré, consiste à utiliser un comparateur anonyme:

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());
    } });
Était-ce utile?

La solution

Je pense que votre solution est le seul moyen sensé. La seule façon d'obtenir la liste des fichiers est d'utiliser File.listFiles () et la documentation indique que cela ne donne aucune garantie quant à l'ordre des fichiers renvoyés. Par conséquent, vous devez écrire un comparateur qui utilise File.lastModified () et transmettez-le, ainsi que le tableau de fichiers, à Arrays.sort () .

Autres conseils

Cela pourrait être plus rapide si vous avez plusieurs fichiers. Ceci utilise le modèle decorate-sort-undecorate de sorte que la date de dernière modification de chaque fichier ne soit extraite que une fois plutôt qu'à chaque fois que l'algorithme de tri compare deux fichiers. Cela réduit potentiellement le nombre d'appels d'E / S de O (n log n) à O (n).

C'est plus de code, cependant, donc cela ne devrait être utilisé que si vous êtes principalement préoccupé par la vitesse et il est nettement plus rapide en pratique (que je n'ai pas vérifié).

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;

Qu'en est-il d'une approche similaire, mais sans boxe aux objets longs:

File[] files = directory.listFiles();

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

Solution élégante depuis Java 8:

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

Ou, si vous le souhaitez dans l'ordre décroissant, inversez-le:

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

Vous pouvez également consulter IO apache commons , il est intégré dans dernier comparateur modifié et de nombreux autres utilitaires permettant de travailler avec des fichiers.

En Java 8:

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

Importations:

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

    }

Si les fichiers que vous triez peuvent être modifiés ou mis à jour en même temps, le tri est effectué:

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


Ces deux solutions créent une structure de données de carte temporaire pour économiser une dernière heure de modification constante pour chaque fichier du répertoire. Cela est dû au fait que si vos fichiers sont mis à jour ou modifiés en même temps que votre tri, votre comparateur ne respectera pas l'exigence de transitivité du contrat général de l'interface du comparateur, car les dernières heures modifiées risquent d'être modifiées au cours de la comparaison.

Si, par contre, vous savez que les fichiers ne seront ni mis à jour ni modifiés au cours de votre tri, vous pouvez vous en tirer avec à peu près n'importe quelle autre réponse soumise à cette question.

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

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

Vous pouvez essayer la goyave Commande :

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

Vous pouvez utiliser Apache LastModifiedFileComparator bibliothèque

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

listFiles est la collection de tous les fichiers de ArrayList

Je suis arrivé à ce poste alors que je cherchais le même problème, mais dans android . Je ne dis pas que c’est le meilleur moyen d’obtenir des fichiers triés par date de dernière modification, mais c’est le moyen le plus simple que j’ai trouvé à ce jour.

Le code ci-dessous peut être utile à quelqu'un -

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
    }

Merci

Il existe un moyen très simple et pratique de traiter le problème sans comparateur supplémentaire. Codez simplement la date modifiée dans la chaîne avec le nom du fichier, triez-la et supprimez-la ultérieurement.

Utilisez une chaîne de longueur fixe 20, insérez-y la date de modification (longue) et remplissez-la de zéros à gauche. Ensuite, ajoutez simplement le nom de fichier à cette chaîne:

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

Que se passe-t-il ici:

Nom du fichier1: C: \ data \ fichier1.html Dernière mise à jour: 1532914451455 Dernière mise à jour 20 chiffres: 00000001532914451455

Nom du fichier1: C: \ data \ fichier2.html Dernière mise à jour: 1532918086822 Dernière mise à jour 20 chiffres: 00000001532918086822

transforme les noms de fichiers en:

Nom du fichier1: 00000001532914451455C: \ data \ fichier1.html

Nom de fichier2: 00000001532918086822C: \ data \ fichier2.html

Vous pouvez ensuite trier cette liste.

Tout ce que vous avez à faire est de supprimer les 20 caractères ultérieurement (dans Java 8, vous pouvez le supprimer pour tout le tableau avec une seule ligne à l'aide de la fonction .replaceAll)

Il existe également une méthode complètement différente qui peut être encore plus facile, car nous ne traitons pas de grands nombres.

Au lieu de trier tout le tableau après avoir récupéré tous les noms de fichiers et les dates lastModified, vous pouvez simplement insérer chaque nom de fichier juste après l'avoir récupéré au bon endroit de la liste.

Vous pouvez le faire comme ceci:

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

Après avoir ajouté l'objet2 à la position 2, l'objet 3 sera déplacé à la position 3.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top