web-dev-qa-db-fra.com

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

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.

Edit: 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());
    } });
215
cwick

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 garantit pas l'ordre des fichiers retournés. Par conséquent, vous devez écrire un Comparator qui utilise File.lastModified () et le transmettre avec le tableau de fichiers à Arrays.sort () .

92
Dan Dyer

Cela pourrait être plus rapide si vous avez beaucoup de fichiers. Ceci utilise le modèle decorate-sort-undecorate afin que la date de dernière modification de chaque fichier ne soit extraite que une fois plutôt que 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, cela ne devrait être utilisé que si vous êtes principalement préoccupé par la vitesse et il est beaucoup plus rapide en pratique (ce 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;
44
Jason Orendorff

Qu'en est-il de l'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());
    }
});
32
PhannGor

Vous pouvez également regarder Apache commons IO , il possède un comparateur intégré last modified et de nombreux autres utilitaires Nice permettant de travailler avec des fichiers.

23
user17163

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

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 Collection<File> result = 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 result;
}


Ces deux solutions créent une structure de données de mappe temporaire pour enregistrer 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 toute autre réponse soumise à cette question.

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

Vous pouvez utiliser 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

Vous pouvez essayer de 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);
1
Vitalii Fedorenko
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

0
Anand Savjani

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 ça:

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

Une fois que vous avez ajouté objet2 à la position 2, l’objet3 sera déplacé à la position 3. 

0
user4378029

Il existe un moyen très simple et pratique de traiter le problème sans aucun 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, mettez-y la date modifiée (longue) et remplissez-la de zéros non significatifs. 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());

Qu'est-ce qui se passe est-ce 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 de fichier1: 00000001532914451455C:\data\fichier1.html

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

Vous pouvez alors simplement 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).

0
user4378029

Je suis arrivé à ce poste alors que je recherchais 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

0
ezcodr