jak File.listFiles w kolejności alfabetycznej?

95

Mam kod jak poniżej:

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

FileFilterPracuje ładnie, ale listFiles()wydaje się być wymieniając pliki w odwrotnej kolejności alfabetycznej. Czy jest jakiś szybki sposób listFile()polecenia wyświetlenia plików w porządku alfabetycznym?

Thunder Rabbit
źródło
1
Zamiast używać wyrażenia regularnego, użyj .endsWith(".xml")zamiast tego.
Fred

Odpowiedzi:

221

listFilesMetoda, z lub bez filtra nie gwarantuje dowolnej kolejności.

Zwraca jednak tablicę, którą można sortować Arrays.sort().

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

To działa, ponieważ Filejest porównywalną klasą, która domyślnie sortuje ścieżki leksykograficzne. Jeśli chcesz je posortować w inny sposób, możesz zdefiniować własny komparator.

Jeśli wolisz korzystać ze strumieni:

Bardziej nowoczesne podejście jest następujące. Aby wydrukować nazwy wszystkich plików w danym katalogu, w kolejności alfabetycznej, wykonaj:

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

Zastąp System.out::printlncokolwiek chcesz zrobić z nazwami plików. Jeśli chcesz tylko nazwy plików, które kończą się na, "xml"po prostu wykonaj:

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

Ponownie, zamień drukowanie na dowolną operację przetwarzania.

Ray Toal
źródło
To piękna linia kodu, ale Arrays.sort () wydaje się zwracać void zamiast iterowalnego. Trochę się pokręcę.
Thunder Rabbit
3
@ Thunder Rabbit, My Apologies !! Tak mi przykro, masz rację. Powinienem był to przetestować. Zmieniłem odpowiedź.
Ray Toal
Wydaje się, że działa dobrze w systemie Windows, ale w Ubuntu foldery z dużymi literami pojawiają się jako pierwsze niż pozostałe.
jmhostalet
5
Tak właśnie spodziewałbym się, że będzie działać. Wielkie litery występują przed małymi literami w Unicode. W Uniksach w nazwach plików rozróżniana jest wielkość liter, więc wielkie litery są pierwsze. Jeśli używasz w systemie Windows nazw plików bez rozróżniania wielkości liter, wielkie i małe litery zostaną pomieszane. Jest to całkowicie zgodne z oczekiwaniami. Jeśli chcesz używać systemu Windows na Uniksie, podaj komparator do sort.
Ray Toal
2

Myślę, że poprzednia odpowiedź jest najlepszym sposobem, aby to zrobić, jest to inny prosty sposób. po prostu wydrukować posortowane wyniki.

 String path="/tmp";
 String[] dirListing = null;
 File dir = new File(path);
 dirListing = dir.list();
 Arrays.sort(dirListing);
 System.out.println(Arrays.deepToString(dirListing));
grepit
źródło
czy mógłbyś podać komentarz, ponieważ uważasz, że to nie jest poprawna odpowiedź. Mogę więc odpowiednio to zmienić.
grepit
1
-1 Naprawdę nie rozumiem korzyści z przekonwertowania tablicy plików na tablicę ciągów, a następnie sortowania, a nie tylko sortowania tablicy plików, tak jak robi to akceptowana odpowiedź.
zelanix
@zelanix dzięki za przesłanie opinii. Nie mam wszystkich odpowiedzi i czasami popełniam błędy odpowiadając na pytania. Zaktualizowałem odpowiedź, czy mógłbyś ją przejrzeć i sprawdzić, czy jest to lepsze rozwiązanie. Byłbym wdzięczny, gdybyś mógł ponownie rozważyć swój głos. Z góry dziękuję.
grepit
1
Ok, teraz uzasadnij, dlaczego jest to prostsze, jeśli chcesz tylko wydrukować wyniki, więc usunę mój głos przeciw.
zelanix,
3
@ CPU100 Uważam, że użycie list () zamiast listFiles () daje tę zaletę, że mają tylko nazwy plików bez ścieżek katalogu nadrzędnego, co skutkuje krótszymi ciągami i krótszym czasem procesora do sortowania / porównywania.
Diljeet
1

W Javie 8:

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

Odwrotna kolejność:

Arrays.sort(files, (a, b) -> -a.getName().compareTo(b.getName()));
Siergiej Rodionow
źródło
2
Możesz też użyć tego kodu:Arrays.sort(fList, Comparator.comparing(File::getName));
Plaidshirt
Uważaj z tym. Ten kod nie jest deterministyczny i nie powinien być używany w takiej postaci, w jakiej jest.
Tony Schwartz
0

To jest mój kod:

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

Tru Nguyen
źródło