como File.listFiles em ordem alfabética?


95

Eu tenho o código abaixo:

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

O FileFilterestá funcionando bem, mas listFiles()parece listar os arquivos em ordem alfabética reversa. Existe alguma maneira rápida de dizer listFile()para listar os arquivos em ordem alfabética?


1
Em vez de usar regex, use .endsWith(".xml").
Fred,

Respostas:


221

O listFilesmétodo, com ou sem filtro, não garante nenhum pedido.

No entanto, ele retorna uma matriz, com a qual você pode classificar Arrays.sort().

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

Isso funciona porque Fileé uma classe comparável, que por padrão classifica os nomes de caminho lexicograficamente. Se quiser classificá-los de forma diferente, você pode definir seu próprio comparador.

Se você preferir usar Streams:

Uma abordagem mais moderna é a seguinte. Para imprimir os nomes de todos os arquivos em um determinado diretório, em ordem alfabética, faça:

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

Substitua o System.out::printlncom o que você deseja fazer com os nomes dos arquivos. Se você quiser apenas nomes de arquivos que terminam com, "xml"faça o seguinte:

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

Novamente, substitua a impressão por qualquer operação de processamento que você deseja.


Esta é uma bela linha de código, mas Arrays.sort () parece retornar void, em vez de um Iterable. Vou bisbilhotar um pouco.
Thunder Rabbit

3
@Thunder Rabbit, My Apologies !! Sinto muito, você está certo. Eu deveria ter testado. Eu editei minha resposta.
Ray Toal

Parece estar funcionando bem no Windows, mas no Ubuntu as pastas com letras maiúsculas aparecem primeiro do que o resto.
jmhostalet

5
É assim que eu esperava que funcionasse. As letras maiúsculas vêm antes das letras minúsculas no Unicode. Unixes têm nomes de arquivo que diferenciam maiúsculas de minúsculas, então as letras maiúsculas vêm primeiro. Se você estiver usando nomes de arquivo que não diferenciam maiúsculas de minúsculas no Windows, os nomes em maiúsculas e minúsculas serão misturados. Isso é completamente o esperado. Se você quiser usar o Windows em um Unix, forneça um comparador para sort.
Ray Toal

2

Acho que a resposta anterior é a melhor maneira de fazer isso aqui é outra maneira simples. apenas para imprimir os resultados classificados.

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

você poderia comentar por que você acha que esta não é uma resposta correta. Portanto, posso revisá-lo de acordo.
grepit de

1
-1 Eu realmente não entendo a vantagem de converter a matriz de arquivo em uma matriz de string e, em seguida, classificar em vez de apenas classificar a matriz de arquivo como faz a resposta aceita.
zelanix de

@zelanix obrigado por fornecer o feedback. Não tenho todas as respostas e às vezes cometo erros ao responder às perguntas. Eu atualizei a resposta. Você poderia revisá-la e ver se esta é uma solução melhor. Eu agradeceria se você pudesse reconsiderar seu voto. Desde já, obrigado.
grepit de

1
Ok, agora você justifica porque é mais simples se você quiser apenas imprimir os resultados, então irei remover meu voto negativo.
zelanix de

3
@ CPU100, acredito que usar list () em vez de listFiles () oferece a vantagem de ter apenas os nomes dos arquivos sem os caminhos do diretório pai, resultando em strings mais curtas e menos tempo de CPU para classificar / comparar.
Diljeet

1

Em Java 8:

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

Ordem reversa:

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

2
Você também pode usar este código:Arrays.sort(fList, Comparator.comparing(File::getName));
camisa xadrez

Cuidado com isso. Este código não é determinístico e não deve ser usado como está.
Tony Schwartz

0

Este é o meu código:

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.