So lesen Sie eine große Datei effizient mit Java

1. Übersicht

Dieses Tutorial zeigt, wie Sie alle Zeilen einer großen Datei in Java auf effiziente Weise lesen können .

Dieser Artikel ist Teil des Tutorials „ Java - Back to Basic “ hier auf Baeldung.

2. Lesen im Speicher

Die Standardmethode zum Lesen der Zeilen der Datei befindet sich im Speicher. Sowohl Guava als auch Apache Commons IO bieten eine schnelle Möglichkeit, genau das zu tun:

Files.readLines(new File(path), Charsets.UTF_8);
FileUtils.readLines(new File(path));

Das Problem bei diesem Ansatz ist, dass alle Dateizeilen im Speicher bleiben - was schnell zu OutOfMemoryError führt, wenn die Datei groß genug ist.

Zum Beispiel - Lesen einer ~ 1 GB-Datei :

@Test public void givenUsingGuava_whenIteratingAFile_thenWorks() throws IOException { String path = ... Files.readLines(new File(path), Charsets.UTF_8); }

Dies beginnt mit einer geringen Menge an Speicher, die verbraucht wird: (~ 0 MB verbraucht)

[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 128 Mb [main] INFO org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 116 Mb

Doch nach der vollständigen Datei verarbeitet wurde , wir am Ende haben: (~ 2 Gb verbraucht)

[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 2666 Mb [main] INFO org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 490 Mb

Dies bedeutet, dass etwa 2,1 GB Speicher von dem Prozess verbraucht werden - der Grund ist einfach - die Zeilen der Datei werden jetzt alle im Speicher gespeichert.

An diesem Punkt sollte klar sein, dass der Inhalt der Datei den verfügbaren Speicher schnell erschöpft, unabhängig davon, wie viel das tatsächlich ist.

Darüber hinaus benötigen wir normalerweise nicht alle Zeilen in der Datei auf einmal im Speicher. Stattdessen müssen wir nur in der Lage sein, jede einzelne Zeile zu durchlaufen, sie zu verarbeiten und wegzuwerfen. Genau das werden wir also tun - durch die Zeilen iterieren, ohne sie alle im Gedächtnis zu behalten.

3. Streaming durch die Datei

Schauen wir uns nun eine Lösung an - wir werden einen java.util.Scanner verwenden , um den Inhalt der Datei zu durchlaufen und Zeilen nacheinander seriell abzurufen:

FileInputStream inputStream = null; Scanner sc = null; try { inputStream = new FileInputStream(path); sc = new Scanner(inputStream, "UTF-8"); while (sc.hasNextLine()) { String line = sc.nextLine(); // System.out.println(line); } // note that Scanner suppresses exceptions if (sc.ioException() != null) { throw sc.ioException(); } } finally { if (inputStream != null) { inputStream.close(); } if (sc != null) { sc.close(); } }

Diese Lösung durchläuft alle Zeilen in der Datei - ermöglicht die Verarbeitung jeder Zeile - ohne Verweise darauf zu behalten - und abschließend, ohne sie im Speicher zu behalten : (~ 150 MB verbraucht)

[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 763 Mb [main] INFO org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 605 Mb

4. Streaming mit Apache Commons IO

Dasselbe kann auch mit der Commons IO-Bibliothek erreicht werden, indem der von der Bibliothek bereitgestellte benutzerdefinierte LineIterator verwendet wird:

LineIterator it = FileUtils.lineIterator(theFile, "UTF-8"); try { while (it.hasNext()) { String line = it.nextLine(); // do something with line } } finally { LineIterator.closeQuietly(it); }

Da sich die gesamte Datei nicht vollständig im Speicher befindet, führt dies auch zu ziemlich konservativen Speicherverbrauchszahlen : (~ 150 MB verbraucht)

[main] INFO o.b.java.CoreJavaIoIntegrationTest - Total Memory: 752 Mb [main] INFO o.b.java.CoreJavaIoIntegrationTest - Free Memory: 564 Mb

5. Schlussfolgerung

Dieser kurze Artikel zeigt, wie Sie Zeilen in einer großen Datei ohne iterative Verarbeitung verarbeiten können, ohne den verfügbaren Speicher zu erschöpfen. Dies ist sehr nützlich, wenn Sie mit diesen großen Dateien arbeiten.

Die Implementierung all dieser Beispiele und Codefragmente finden Sie in unserem GitHub-Projekt - dies ist ein Maven-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein, wie es ist.