2015-11-06 27 views
5

Ho una directory con 100.000 file e ho bisogno di iterarli tutti per leggere un valore. In questo momento io uso listFiles() per caricare tutti i file in una matrice e quindi iterare uno per uno. Ma esiste un modo efficiente di memoria per farlo senza caricare in un array?Iterate un grande insieme di file in una directory

File[] tFiles = new File(Dir).listFiles(); 

try { 
    for (final File tFile : tFiles) { 
     //Process files one by one 
    } 
} 
+0

[Una risposta che ho dato in precedenza potrebbe aiutare] (http://stackoverflow.com/questions/27898652/how-to-read-multiple-text-files-in-java-for-gui-use-didnt-find-the-answer/27900034#27900034) È necessario modificare alcune funzionalità ma utilizzare gli stream potrebbe essere più efficiente. Non sono sicuro delle prestazioni, comunque. – easyDaMan

risposta

6

Poiché Java 7, è possibile utilizzare il modello di visitatore del file per visitare i contenuti di una directory in modo ricorsivo.

La documentazione per l'interfaccia FileVisitor è here.

Ciò consente di eseguire iterazioni sui file senza creare una vasta gamma di oggetti File.

semplice esempio per stampare i nomi di file:

Path start = Paths.get(new URI("file:///my/folder/")); 

Files.walkFileTree(start, new SimpleFileVisitor<Path>() { 
    @Override 
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) 
     throws IOException 
    { 
     System.out.println(file); 
     return FileVisitResult.CONTINUE; 
    } 
    @Override 
    public FileVisitResult postVisitDirectory(Path dir, IOException e) 
     throws IOException 
    { 
     if (e == null) { 
      System.out.println(dir); 
      return FileVisitResult.CONTINUE; 
     } 
     else { 
      // directory iteration failed 
      throw e; 
     } 
    } 
}); 
+0

Grazie! questo era esattamente quello che stavo cercando :) – prem89

+0

@ prem89 siete i benvenuti! – Mena

1

Se si vuole evitare il boilerplate eccessivo che viene fornito con JDK di FileVisitor, è possibile utilizzare Guava. Files.fileTreeTraverser() ti dà una TreeTraverser<File> che si può usare per attraversare i file nella cartella (o anche sottocartelle):

for (File f : Files.fileTreeTraverser() 
        .preOrderTraversal(new File("/parent/folder"))) { 
    // do something with each file 
} 
+0

Questo chiama internamente 'Collections.unmodifiableList (Arrays.asList (file)) ;,, cioè non penso che sia meglio come il codice della domanda stessa. – jan

+0

@jan, dipende da cosa intendi con "migliore". Mi piace "TreeTraverser" di Guava perché è un'astrazione davvero potente che rende possibile fare la tua cosa in maniera succinta e leggibile, lasciando meno spazio agli errori. Sì, potrebbe non essere la soluzione più performante, ma nella maggior parte dei casi questo non è probabilmente il collo di bottiglia dell'applicazione. Questo può valere anche nel caso dell'OP con file 100k. Vorrei innanzitutto utilizzare la soluzione più semplice possibile e ottimizzare solo le prestazioni se la soluzione più semplice possibile non è abbastanza buona. –

+0

In altre circostanze sarei totalmente d'accordo, ma come risposta/commento in questa domanda riguardante una soluzione efficiente non posso essere d'accordo. E potrebbero esserci anche più file come 100k. – jan

2

Java 8 pigramente caricato versione corrente:

Files.list(new File("path to directory").toPath()).forEach(path -> { 
    File file = path.toFile(); 
    //process your file 
});