2010-01-13 15 views
11

Cuando lista archivos de un directorio que tiene 300,000 archivos con Java, se produce falta de memoria.OutOfMemory cuando lista archivos en un directorio

String[] fileNames = file.list(); 

Lo que yo quiero es una forma que puede listar todos los archivos de un directorio de forma incremental independientemente del número de archivos en ese directorio específico y no tendrá "sin memoria" problema con el límite del montón 64M defecto.

Tengo Google un tiempo, y no puedo encontrarlo en Java puro.
Por favor, ayúdenme !!

Nota, JNI es una posible solución, pero odio JNI.

+0

¿El requisito de límite de almacenamiento intermedio de 64MB es difícil? ¿También tiene otras partes de su código que asigna una gran cantidad de objetos? – notnoop

+0

64 MB no es un límite estricto. Sin embargo, queremos usar Java para monitorear una carpeta en la que nuestros clientes carguen grandes cantidades de archivos. Y no sabemos cuánta memoria es suficiente. – James

+0

Una vez que los hayas enumerado todos, ¿qué vas a hacer con el resultado? – OscarRyz

Respuesta

5

Sé que dijiste "con el límite de almacenamiento dinámico predeterminado de 64M", pero veamos los hechos: desea mantener una cantidad (potencialmente) grande de elementos en la memoria, utilizando los mecanismos puestos a su disposición por Java. Entonces, a menos que haya alguna razón grave que no pueda, yo diría que aumentar el montón es el camino a seguir.

Aquí hay un enlace a la misma discusión en JavaRanch: http://www.coderanch.com/t/381939/Java-General/java/iterate-over-files-directory

Editar, en respuesta a comentar: la razón por la que dijo que quiere llevar a cabo una gran cantidad de elementos en la memoria se debe a que este es el único El mecanismo de Java proporciona la lista de un directorio sin utilizar la interfaz nativa o los mecanismos específicos de la plataforma (y OP dijo que quería "Java puro").

+1

The llamar que James está haciendo devoluciones una matriz. La pregunta se reduce a si de alguna manera puede obtener el equivalente de un iterador para los nombres en el directorio, sin asignar el conjunto completo a la vez. Es una pregunta razonable; No sé la respuesta en la parte superior de mi cabeza. –

+2

No se puede con la API Java central. – danben

+0

Sí, lo que quiero es exactamente un FileIterator – James

1

Tener 300 000 archivos en un directorio no es una buena idea: los sistemas de archivos AFAIK no son buenos para tener tantos nodos secundarios en un solo nodo. Interesante pregunta, sin embargo.

EDITAR: LAS SIGUIENTES NO AYUDAN, ver comentarios.

Creo que podría utilizar un FileFilter, rechazar todos los archivos y procesarlos en el filtro.

 new File("c:/").listFiles(new FileFilter() { 
      @Override public boolean accept(File pathname) { 
       processFile(); 
       return false; 
      } 
     }); 
+0

XFS admite una gran cantidad de archivos en un único directorio. Además, esta respuesta está bastante lejos del tema. – danben

+1

Acabo de comprobar el origen de java.io.File. Llamará a la lista antes de filtrar de todos modos para que el problema original persista. – Gennadiy

+0

Sí, deseo que las personas al menos verifiquen las respuestas que "se ven bien" antes de modelar. Sin ofender destinado al cartel. – danben

2

Te encuentras un poco de suerte aquí. Al menos habrá que crear cadenas de 300k. Con una longitud promedio de 8-10 char y 2 bytes por char, eso es 6Mb en el mínimo. Agregue la sobrecarga del puntero del objeto por cadena (8 bytes) y se encontrará con su límite de memoria.

Si absolutamente debe tener tantos archivos en un solo directorio, lo que no recomendaría ya que su sistema de archivos tendrá problemas, su mejor opción es ejecutar un proceso nativo (no JNI) a través de Runtime.exec. Tenga en cuenta que se relacionará con el SO (ls vs dir). Podrá obtener una lista de archivos como una cadena grande y será responsable de procesarla en lo que desee.

Espero que esto ayude.

3

La única solución posible para usted es Java7 y luego puede usar un iterador.

final Path p = FileSystems.getDefault().getPath("Yourpath"); 
Files.walk(p).forEach(filePath -> { 
     if (Files.isRegularFile(filePath)) { 
      //Do something with filePath 
     } 
}); 
+2

En http://stackoverflow.com/questions/3139073/how-to-list-a-2-million-files-directory-in-java-without-having-a-out-of-memory-e/14241968# 14241968 He publicado un ejemplo simple de cómo hacer esto con Java 7 –

+0

['Path.iterator()'] (https://docs.oracle.com/javase/7/docs/api/java/nio/file /Path.html#iterator() itera sobre los elementos de nombre de una ruta, no sobre los archivos en un directorio. – predi

0

Si puede escribir su código en Java 7 o superior, entonces el siguiente es una buena opción.

Files.newDirectoryStream (dir Path)

Here es el doc java para el API.

Espero que esto ayude.

Cuestiones relacionadas