¿Cómo File.listFiles en orden alfabético?


95

Tengo el siguiente código:

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

El FileFilterestá funcionando bien, pero listFiles()parece estar listando los archivos en orden alfabético inverso. ¿Existe alguna forma rápida de decirle listFile()que enumere los archivos en orden alfabético?


1
En lugar de usar expresiones regulares, use .endsWith(".xml")en su lugar.
Fred

Respuestas:


221

El listFilesmétodo, con o sin filtro, no garantiza ningún pedido.

Sin embargo, devuelve una matriz, con la que puede ordenar Arrays.sort().

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

Esto funciona porque Filees una clase comparable, que por defecto ordena los nombres de ruta lexicográficamente. Si desea ordenarlos de manera diferente, puede definir su propio comparador.

Si prefiere usar Streams:

Un enfoque más moderno es el siguiente. Para imprimir los nombres de todos los archivos de un directorio determinado, en orden alfabético, haga lo siguiente:

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

Reemplace el System.out::printlncon lo que quiera hacer con los nombres de archivo. Si solo desea nombres de archivo que terminen con "xml"simplemente haga:

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

Nuevamente, reemplace la impresión con la operación de procesamiento que desee.


Esta es una hermosa línea de código, pero Arrays.sort () parece devolver void, en lugar de Iterable. Voy a hurgar un poco.
Thunder Rabbit

3
@ Thunder Rabbit, ¡¡Mis disculpas !! Lo siento, tienes razón. Debería haberlo probado. Edité mi respuesta.
Ray Toal

Parece que funciona bien en Windows, pero en Ubuntu las carpetas con mayúsculas aparecen primero que el resto.
jmhostalet

5
Esa es la forma en que espero que funcione. Las letras mayúsculas van antes de las minúsculas en Unicode. Los Unix tienen nombres de archivo que distinguen entre mayúsculas y minúsculas, por lo que las letras mayúsculas son lo primero. Si está utilizando nombres de archivo que no distinguen entre mayúsculas y minúsculas en Windows, los nombres en mayúsculas y minúsculas se mezclarán. Esto es completamente como se esperaba. Si desea el método de Windows en Unix, proporcione un comparador a sort.
Ray Toal

2

Creo que la respuesta anterior es la mejor manera de hacerlo, aquí es otra forma sencilla. solo para imprimir los resultados ordenados.

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

¿Podría comentar por qué cree que esta no es una respuesta correcta? Entonces, puedo revisarlo en consecuencia.
grepit

1
-1 Realmente no entiendo la ventaja de convertir la matriz de archivos en una matriz de cadenas y luego ordenar en lugar de simplemente ordenar la matriz de archivos como lo hace la respuesta aceptada.
zelanix

@zelanix gracias por brindarnos sus comentarios. No tengo todas las respuestas y a veces cometo errores al contestar las preguntas. He actualizado la respuesta, ¿podría revisarla y ver si esta es una mejor solución? Le agradecería que reconsiderara su voto. Gracias por adelantado.
grepit

1
Ok, ahora justifica por qué es más simple si solo desea imprimir los resultados, así que eliminaré mi voto negativo.
zelanix

3
@ CPU100 creo que usar list () en lugar de listFiles () da la ventaja de tener solo los nombres de archivo sin las rutas del directorio principal, lo que resulta en cadenas más cortas y menos tiempo de CPU para ordenar / comparar.
Diljeet

1

En Java 8:

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

Orden inverso:

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

2
También puede usar este código:Arrays.sort(fList, Comparator.comparing(File::getName));
plaidshirt

Tenga cuidado con esto. Este código no es determinista y no debe usarse tal cual.
Tony Schwartz

0

Este es mi codigo:

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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.