Ich muss eine große Textdatei von etwa 5-6 GB zeilenweise mit Java lesen.
Wie kann ich das schnell erledigen?
Ich muss eine große Textdatei von etwa 5-6 GB zeilenweise mit Java lesen.
Wie kann ich das schnell erledigen?
Ein gängiges Muster ist die Verwendung von
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
while ((line = br.readLine()) != null) {
// process the line.
}
}
Sie können die Daten schneller lesen, wenn Sie davon ausgehen, dass es keine Zeichenkodierung gibt, z. B. ASCII-7, aber das wird keinen großen Unterschied machen. Es ist sehr wahrscheinlich, dass das, was Sie mit den Daten machen, viel länger dauern wird.
EDIT: Ein weniger häufig verwendetes Muster, das den Anwendungsbereich von line
undicht.
try(BufferedReader br = new BufferedReader(new FileReader(file))) {
for(String line; (line = br.readLine()) != null; ) {
// process the line.
}
// line is not visible here.
}
UPDATE: In Java 8 können Sie Folgendes tun
try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
stream.forEach(System.out::println);
}
HINWEIS: Sie müssen den Stream in einem Versuch-mit-Ressource Block, um sicherzustellen, dass die #close-Methode darauf aufgerufen wird, sonst wird das zugrundeliegende Dateihandle nie geschlossen, bis GC es viel später tut.
Wie sieht dieses Muster bei ordnungsgemäßer Ausnahmebehandlung aus? Ich stelle fest, dass br.close() eine IOException auslöst, was überraschend erscheint - was könnte beim Schließen einer Datei, die zum Lesen geöffnet ist, überhaupt passieren? Der Konstruktor von FileReader könnte eine FileNotFound-Ausnahme auslösen.
@MikeB In Java 7 würden Sie einen try-with-resource-Block hinzufügen. Es wird nicht erwartet, dass Close eine Ausnahme auslöst, aber einige Implementierungen könnten dies tun. Ich würde nicht erwarten, dass BufferedReader eine davon ist. Es ist sehr selten, dass Entwickler eine spezielle Behandlung für close();
Ist das die schnellste Geschwindigkeit, die Java erreichen kann? Ich habe eine ~200MB große Datei, die ich mit dieser Methode lese und die wirklich langsam ist ... ist es möglich, etwas schnelleres zu verwenden? Mehrere Zeilen einlesen oder so?
Sehen Sie sich diesen Blog an:
Die Puffergröße kann angegeben werden, oder die Standardgröße kann verwendet werden. Die Vorgabe ist für die meisten Zwecke groß genug Zwecke.
// Open the file
FileInputStream fstream = new FileInputStream("textfile.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
String strLine;
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
// Print the content on the console
System.out.println (strLine);
}
//Close the input stream
fstream.close();
Meine Datei ist 1,5 Gigabyte groß und es ist nicht möglich, die Datei mit Ihrer Antwort zu lesen!
Heruntergestuft wegen schlechter Qualität des Links. Es gibt einen völlig sinnlosen DataInputStream
und der falsche Stream wird geschlossen. Am Java-Tutorial ist nichts auszusetzen, und es besteht keine Notwendigkeit, willkürlichen Internet-Müll von Dritten zu zitieren.
Sobald Java 8 verfügbar ist (März 2014), werden Sie Streams verwenden können:
try (Stream<String> lines = Files.lines(Paths.get(filename), Charset.defaultCharset())) {
lines.forEachOrdered(line -> process(line));
}
Drucken aller Zeilen der Datei:
try (Stream<String> lines = Files.lines(file, Charset.defaultCharset())) {
lines.forEachOrdered(System.out::println);
}
Utilice StandardCharsets.UTF_8
verwenden Stream<String>
der Prägnanz halber und um die Verwendung von forEach()
und insbesondere forEachOrdered()
es sei denn, es gibt einen Grund dafür.
Wenn ich forEach anstelle von forEachOrdered verwende, werden die Zeilen möglicherweise nicht in der richtigen Reihenfolge gedruckt, oder?
Hier ist ein Beispiel mit vollständiger Fehlerbehandlung und unterstützender Zeichensatzspezifikation für die Zeit vor Java 7. Mit Java 7 können Sie die Syntax try-with-resources verwenden, die den Code sauberer macht.
Wenn Sie nur den Standardzeichensatz wünschen, können Sie den InputStream überspringen und FileReader verwenden.
InputStream ins = null; // raw byte-stream
Reader r = null; // cooked reader
BufferedReader br = null; // buffered for readLine()
try {
String s;
if (true) {
String data = "#foobar\t1234\n#xyz\t5678\none\ttwo\n";
ins = new ByteArrayInputStream(data.getBytes());
} else {
ins = new FileInputStream("textfile.txt");
}
r = new InputStreamReader(ins, "UTF-8"); // leave charset out for default
br = new BufferedReader(r);
while ((s = br.readLine()) != null) {
System.out.println(s);
}
}
catch (Exception e)
{
System.err.println(e.getMessage()); // handle exception
}
finally {
if (br != null) { try { br.close(); } catch(Throwable t) { /* ensure close happens */ } }
if (r != null) { try { r.close(); } catch(Throwable t) { /* ensure close happens */ } }
if (ins != null) { try { ins.close(); } catch(Throwable t) { /* ensure close happens */ } }
}
Hier ist die Groovy-Version, mit vollständiger Fehlerbehandlung:
File f = new File("textfile.txt");
f.withReader("UTF-8") { br ->
br.eachLine { line ->
println line;
}
}
Was bedeutet ein ByteArrayInputStream
mit einem String-Literal gefüttert werden, mit dem Lesen einer großen Textdatei zu tun haben?
Ich habe dokumentiert und getestet 10 verschiedene Möglichkeiten, eine Datei in Java zu lesen und ließen sie dann gegeneinander antreten, indem sie Testdateien von 1 KB bis 1 GB einlesen mussten. Hier sind die 3 schnellsten Methoden zum Einlesen einer 1 GB großen Testdatei.
Beachten Sie, dass ich bei der Durchführung der Leistungstests nichts auf der Konsole ausgegeben habe, da dies den Test stark verlangsamen würde. Ich wollte nur die reine Lesegeschwindigkeit testen.
1) java.nio.file.Files.readAllBytes()
Getestet in Java 7, 8, 9. Dies war insgesamt die schnellste Methode. Das Lesen einer 1 GB großen Datei dauerte konstant knapp unter 1 Sekunde.
import java.io..File;
import java.io.IOException;
import java.nio.file.Files;
public class ReadFile_Files_ReadAllBytes {
public static void main(String [] pArgs) throws IOException {
String fileName = "c:\\temp\\sample-1GB.txt";
File file = new File(fileName);
byte [] fileBytes = Files.readAllBytes(file.toPath());
char singleChar;
for(byte b : fileBytes) {
singleChar = (char) b;
System.out.print(singleChar);
}
}
}
2) java.nio.file.Files.lines()
Dies wurde erfolgreich in Java 8 und 9 getestet, wird aber in Java 7 nicht funktionieren, da es keine Unterstützung für Lambda-Ausdrücke gibt. Das Einlesen einer 1 GB großen Datei dauerte etwa 3,5 Sekunden, was den zweiten Platz beim Einlesen größerer Dateien bedeutete.
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.stream.Stream;
public class ReadFile_Files_Lines {
public static void main(String[] pArgs) throws IOException {
String fileName = "c:\\temp\\sample-1GB.txt";
File file = new File(fileName);
try (Stream linesStream = Files.lines(file.toPath())) {
linesStream.forEach(line -> {
System.out.println(line);
});
}
}
}
3) GepufferterLeser
Getestet, um in Java 7, 8, 9 zu funktionieren. Das Einlesen einer 1 GB großen Testdatei dauerte etwa 4,5 Sekunden.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ReadFile_BufferedReader_ReadLine {
public static void main(String [] args) throws IOException {
String fileName = "c:\\temp\\sample-1GB.txt";
FileReader fileReader = new FileReader(fileName);
try (BufferedReader bufferedReader = new BufferedReader(fileReader)) {
String line;
while((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
}
}
Hier finden Sie die vollständigen Ranglisten für alle 10 Dateileseverfahren これ .
Sie sind meist zeitlich gebunden System.out.print/println()
Sie gehen auch davon aus, dass die Datei in Ihren ersten beiden Fällen in den Speicher passt.
Das stimmt. Vielleicht hätte ich diese Annahmen in meiner Antwort deutlicher machen sollen.
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
97 Stimmen
@kamaci et. al. Diese Frage sollte nicht als Duplikat markiert werden. "Schnelles Lesen der letzten Zeile" ist keine Alternative, und es ist fraglich, ob "Schnellster Weg, eine Textdatei Zeile für Zeile zu lesen" eine ist. Der schnellste Weg, etwas zu tun, ist nicht unbedingt der übliche Weg. Außerdem enthalten die folgenden Antworten Code, die wichtigste Alternative, die Sie auflisten, jedoch nicht. Diese Frage ist nützlich. Sie ist derzeit das wichtigste Google-Suchergebnis für "java read file line by line". Schließlich ist es ärgerlich, wenn man bei Stack Overflow ankommt und feststellt, dass 1 von 2 Fragen zur Beseitigung vorgemerkt ist.
5 Stimmen
Hier ist ein Vergleich der Geschwindigkeit für sechs mögliche Implementierungen.
5 Stimmen
Obwohl ich in vielen Kommentaren gelesen habe, dass die Schließungspolitik von SO schlecht ist, hält SO an ihr fest. Es ist eine so engstirnige Entwicklerperspektive, Redundanz um jeden Preis vermeiden zu wollen! Lasst es einfach sein! Die Sahne wird nach oben steigen und der Dreck wird von ganz alleine nach unten sinken. Auch wenn eine Frage schon einmal gestellt worden ist (welche Frage ist das nicht??), bedeutet das nicht, dass eine neue Frage nicht besser formuliert werden kann, bessere Antworten erhält, in Suchmaschinen besser platziert wird usw. Interessanterweise ist diese Frage jetzt "geschützt" ....
4 Stimmen
Es ist unglaublich, wie viele Fragen allein durch das Lesen des Titels als doppelt markiert werden.
0 Stimmen
Nach Shogs Bearbeitung ist dies tatsächlich ein Duplikat von stackoverflow.com/q/5800361/103167 aber dieses hat viel mehr Aktivität bekommen.