come File.listFiles in ordine alfabetico?


95

Ho il codice come di seguito:

class ListPageXMLFiles implements FileFilter {

        @Override
        public boolean accept(File pathname) {
                DebugLog.i("ListPageXMLFiles", "pathname is " + pathname);

                String regex = ".*page_\\d{2}\\.xml";
                if(pathname.getAbsolutePath().matches(regex)) {
                        return true;
                }
                return false;
        }
}

public void loadPageTrees(String xml_dir_path) {
        ListPageXMLFiles filter_xml_files = new ListPageXMLFiles();
        File XMLDirectory = new File(xml_dir_path);
        for(File _xml_file : XMLDirectory.listFiles(filter_xml_files)) {
                loadPageTree(_xml_file);
        }
}

La FileFiltersta lavorando bene, ma listFiles()sembra essere l'elenco dei file in ordine alfabetico inverso. C'è un modo rapido per dire listFile()di elencare i file in ordine alfabetico?


1
Invece di usare regex, usa .endsWith(".xml")invece.
Fred

Risposte:


221

Il listFiles metodo, con o senza filtro, non garantisce alcun ordine.

Tuttavia, restituisce un array, con il quale è possibile ordinare Arrays.sort().

File[] files = XMLDirectory.listFiles(filter_xml_files);
Arrays.sort(files);
for(File _xml_file : files) {
    ...
}

Funziona perché Fileè una classe comparabile, che per impostazione predefinita ordina i nomi di percorso in modo lessicografico. Se vuoi ordinarli in modo diverso, puoi definire il tuo comparatore.

Se preferisci usare Streams:

Un approccio più moderno è il seguente. Per stampare i nomi di tutti i file in una determinata directory, in ordine alfabetico, eseguire:

Files.list(Paths.get(dirName)).sorted().forEach(System.out::println)

Sostituisci System.out::printlncon quello che vuoi fare con i nomi dei file. Se vuoi solo nomi di file che finiscono con "xml"fai:

Files.list(Paths.get(dirName))
    .filter(s -> s.toString().endsWith(".xml"))
    .sorted()
    .forEach(System.out::println)

Di nuovo, sostituisci la stampa con qualsiasi operazione di elaborazione desideri.


Questa è una bellissima riga di codice, ma Arrays.sort () sembra restituire void, invece di un Iterable. Guardo un po 'in giro.
Thunder Rabbit

3
@Thunder Rabbit, My Apologies !! Mi dispiace tanto, hai ragione. Avrei dovuto provarlo. Ho modificato la mia risposta.
Ray Toal

Sembra funzionare bene in Windows, ma in Ubuntu le cartelle con le lettere maiuscole appaiono prima del resto.
jmhostalet

5
È così che mi aspetto che funzioni. Le lettere maiuscole vengono prima delle lettere minuscole in Unicode. Gli Unix hanno nomi di file che fanno distinzione tra maiuscole e minuscole, quindi le lettere maiuscole vengono prima. Se utilizzi nomi di file senza distinzione tra maiuscole e minuscole su Windows, i nomi maiuscoli e minuscoli verranno mescolati insieme. Questo è completamente come previsto. Se vuoi il modo Windows su un Unix, fornisci un comparatore a sort.
Ray Toal,

2

Penso che la risposta precedente sia il modo migliore per farlo qui è un altro modo semplice. solo per stampare i risultati ordinati.

 String path="/tmp";
 String[] dirListing = null;
 File dir = new File(path);
 dirListing = dir.list();
 Arrays.sort(dirListing);
 System.out.println(Arrays.deepToString(dirListing));

forniresti un commento per spiegare perché pensi che questa non sia una risposta corretta. Quindi, posso rivederlo di conseguenza.
grepit

1
-1 Non capisco davvero il vantaggio di convertire l'array di file in un array di stringhe e quindi ordinare piuttosto che ordinare semplicemente l'array di file come fa la risposta accettata.
zelanix

@zelanix grazie per aver fornito il feedback. Non ho tutte le risposte ea volte faccio degli errori rispondendo alle domande. Ho aggiornato la risposta, la prego di esaminarla e vedere se questa è una soluzione migliore. Apprezzerei se potesse riconsiderare il suo voto. Grazie in anticipo.
grepit

1
Ok, ora giustifica perché è più semplice se vuoi solo stampare i risultati, quindi rimuoverò il mio voto negativo.
zelanix

3
@ CPU100 credo che l'uso di list () invece di listFiles () offra il vantaggio di avere solo i nomi dei file senza i percorsi della directory principale, risultando in stringhe più brevi e meno tempo della CPU per ordinare / confrontare.
Diljeet

1

In Java 8:

Arrays.sort(files, (a, b) -> a.getName().compareTo(b.getName()));

Ordine inverso:

Arrays.sort(files, (a, b) -> -a.getName().compareTo(b.getName()));

2
Puoi usare anche questo codice:Arrays.sort(fList, Comparator.comparing(File::getName));
plaidshirt

Stai attento con questo. Questo codice non è deterministico e non deve essere utilizzato così com'è.
Tony Schwartz,

0

Questo è il mio codice:

        try {
            String folderPath = "../" + filePath.trim() + "/";
            logger.info("Path: " + folderPath);
            File folder = new File(folderPath);
            File[] listOfFiles = folder.listFiles();
            int length = listOfFiles.length;
            logger.info("So luong files: " + length);
            ArrayList<CdrFileBO> lstFile = new ArrayList< CdrFileBO>();

            if (listOfFiles != null && length > 0) {
                int count = 0;
                for (int i = 0; i < length; i++) {
                    if (listOfFiles[i].isFile()) {
                        lstFile.add(new CdrFileBO(listOfFiles[i]));
                    }
                }
                Collections.sort(lstFile);
                for (CdrFileBO bo : lstFile) {
                    //String newName = START_NAME + "_" + getSeq(SEQ_START) + "_" + DateSTR + ".s";
                    String newName = START_NAME + DateSTR + getSeq(SEQ_START) + ".DAT";
                    SEQ_START = SEQ_START + 1;
                    bo.getFile().renameTo(new File(folderPath + newName));
                    logger.info("newName: " + newName);
                    logger.info("Next file: " + getSeq(SEQ_START));
                }

            }
        } catch (Exception ex) {
            logger.error(ex);
            ex.printStackTrace();
        }

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.