2012-09-03 7 views
12

estoy lista los archivos en un sistema de archivos en Java utilizando la siguiente clase de Apache Commons:¿Puedo comprobar el tamaño de una colección ya que está siendo poblada

Collection<File> allFiles = FileUtils.listFiles(rootDirectory, null, recursive);

Este es un proceso muy largo y puede tomar hasta 5 minutos.

¿Hay alguna manera de verificar el tamaño de la colección mientras se está rellenando?

He intentado acceder desde una hebra separada pero simplemente obtuve cero hasta que el proceso estuvo listo.

Respuesta

2

podría utilizar el FileUtils IOFileFilter.

Collection<File> listFiles = FileUtils.listFiles(new File("."), counter, FileFilterUtils.trueFileFilter()); 

donde contador sería a lo largo de las líneas

IOFileFilter counter = new IOFileFilter() { 

    @Override 
    public boolean accept(File arg0, String arg1) { 
     countCall(); 
     return true; 
    } 

    @Override 
    public boolean accept(File arg0) { 
     countCall(); 
     return true; 
    } 
}; 

y countCall es el método que actualiza progreso.

+0

Esto es muy innovador. Lo intentaré y te responderé – Redandwhite

11

Hasta que obtenga un valor de retorno del método, no podrá acceder a la colección cuando se llene, porque no tiene acceso a la variable que este método usa internamente.

Puede dividir la búsqueda en partes más pequeñas al no usar la bandera recursiva y tratar la recursión usted mismo para recibir una colección por directorio.

Una mejor alternativa, si está utilizando Java 7, es usar the FileVisitor interface to explore the file system. Tiene algunos métodos de devolución de llamada que le permiten seguir el progreso.

+0

+1 por mencionar Filevisitor y callbacks – Pyranja

+0

Desafortunadamente, tengo que usar Java 6, ya que la aplicación necesita funcionar en Mac con la JVM incorporada (Apple todavía envía Java 6!) – Redandwhite

+0

@Redandwhite Creo que su única opción es dividir la búsqueda, a menos que alguien más tenga una mejor idea. – assylias

1

Supongo que puede intentar usar la ejecución de comandos específicos de la plataforma, como redirigir la salida del comando de lista al archivo temporal y leerla con la API de archivos Java.

ls > temp.txt

he creado un simple script de shell que enumerará los archivos en el índice dado.

#!/bin/bash 

RANGE_UP=$2 
RANGE_BOT=$1 

CURRENT_CNTR=0 

FILENAME=._m_ls 

ls -w 1 > $FILENAME 
while read line 
do 
    if [ $CURRENT_CNTR -le $RANGE_UP -a $CURRENT_CNTR -gt $RANGE_BOT ]; then 
    printf $line"\n" 
    fi 
    CURRENT_CNTR=`expr $CURRENT_CNTR + 1` 
done < $FILENAME 

Ahora puede hacer algo como ./ls_range.sh 10000 30000 >temp.txt y luego leer de este archivo usando BufferedReader en un hilo diferente.

1

Su única forma de hacer esto (a diferencia de java7 o dividir el trabajo como se sugirió anteriormente) sería escribir su propio código para buscar a través del sistema de archivos mientras actualiza una devolución de llamada.

Utilicé el código de commons-io, y lo modifiqué para adaptarlo a sus necesidades, obviamente necesita pruebas, pero cuenta los archivos a medida que se encuentran.

Ejemplo

interface Counter { 
    void foundFile(File file); 
} 

final class FileSearcher { 
    public static Collection<File> listFiles(File root, FileFilter filter, Counter counter) { 
     Collection<File> files = new ArrayList<File>(); 
     File[] found = root.listFiles(filter); 

     if (found != null) { 
      for (int i = 0; i < found.length; i++) { 
       if (found[i].isDirectory()) { 
        files.addAll(listFiles(found[i], filter, counter)); 
       } else { 
        files.add(found[i]); 
        counter.foundFile(found[i]); 
       } 
      } 
     } 

     return files; 
    } 
} 

y luego usarlo como esto:

final AtomicInteger inte = new AtomicInteger(0); 
FileSearcher.listFiles(new File("C:/"), null, new Counter() { 
    @Override 
    public void foundFile(File file) { 
     System.out.println("found file number " + inte.addAndGet(1)); 
    } 
}); 
Cuestiones relacionadas