як File.listFiles в алфавітному порядку?


95

У мене є код, як показано нижче:

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

Це FileFilterпрацює добре, але, listFiles()схоже, перераховує файли у зворотному алфавітному порядку. Чи є якийсь швидкий спосіб сказати, listFile()щоб перелічити файли в алфавітному порядку?


1
Замість використання регулярного вираження використовуйте .endsWith(".xml")замість цього.
Фред

Відповіді:


221

listFilesМетод, з фільтром або без нього не гарантує порядок.

Однак він повертає масив, з яким ви можете сортувати Arrays.sort().

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

Це працює, оскільки Fileце порівнянний клас, який за замовчуванням сортує імена шляхів лексикографічно. Якщо ви хочете відсортувати їх по-іншому, ви можете визначити власний компаратор.

Якщо ви віддаєте перевагу використовувати потоки:

Більш сучасний підхід полягає в наступному. Щоб надрукувати імена всіх файлів у даному каталозі, в алфавітному порядку, виконайте:

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

Замініть на System.out::printlnте, що ви хочете зробити з іменами файлів. Якщо ви хочете лише імена файлів, які закінчуються на "xml"just do:

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

Знову ж таки, замініть друк будь-якою операцією обробки, яку ви хотіли б.


Це один прекрасний рядок коду, але Arrays.sort (), здається, повертає порожнечу, замість Iterable. Я тріскаю трохи.
Громовий Кролик

3
@Thunder Кролик, мої вибачення !! Так вибачте, ви праві. Я повинен був це перевірити. Я відредагував свою відповідь.
Ray Toal

Здається, це прекрасно працює в Windows, але в папках Ubuntu з великими літерами з’являються першими, ніж решта.
jmhostalet

5
Ось так я б очікував, що це спрацює. Великі літери стоять перед малими літерами в Unicode. У Unix є назви файлів, чутливі до регістру, тому великі літери стоять на першому місці. Якщо ви використовуєте невідчутні до регістру імена файлів у Windows, великі та малі імена будуть змішані між собою. Це цілком очікувано. Якщо ви хочете, щоб Windows перемістився на Unix, поставте компаратор sort.
Ray Toal

2

Я думаю, що попередня відповідь - найкращий спосіб зробити це тут, це ще один простий спосіб. просто для друку відсортованих результатів.

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

будь ласка, дайте коментар, чому ви вважаєте, що це не правильна відповідь. Отже, я можу переглянути його відповідно.
grepit

1
-1 Я дійсно не розумію переваги перетворення файлового масиву в рядковий масив, а потім сортування, а не просто сортування файлового масиву, як це прийнято.
zelanix

Дякуємо @zelanix за наданий відгук. У мене немає всіх відповідей, і я роблю помилки, часом відповідаючи на питання. Я оновив відповідь, будь ласка, перегляньте її і побачите, чи це краще рішення. Я би вдячний, якщо ви могли б переглянути свій голос. Заздалегідь спасибі.
grepit

1
Добре, тепер ви обґрунтовуєте, чому це простіше, якщо ви просто хочете надрукувати результати, тож я приберу свій голос проти.
zelanix

3
@ CPU100 я вважаю, що використання list () замість listFiles () дає перевагу наявності лише імен файлів без батьківських шляхів до каталогу, що призводить до коротших рядків та меншого часу процесора для сортування / порівняння.
Ділєє

1

У Java 8:

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

Зворотний порядок:

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

2
Ви також можете скористатися цим кодом:Arrays.sort(fList, Comparator.comparing(File::getName));
джемпер

Будьте обережні з цим. Цей код не є детермінованим і не повинен використовуватися як є.
Тоні Шварц

0

Це мій код:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.