1019 Stimmen

Wie kann ich mit Java eine große Textdatei Zeile für Zeile lesen?

Ich muss eine große Textdatei von etwa 5-6 GB zeilenweise mit Java lesen.

Wie kann ich das schnell erledigen?

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" ....

1249voto

Peter Lawrey Punkte 511323

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.

7 Stimmen

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.

0 Stimmen

@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();

0 Stimmen

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?

187voto

Naveed Punkte 40250

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();

8 Stimmen

Meine Datei ist 1,5 Gigabyte groß und es ist nicht möglich, die Datei mit Ihrer Antwort zu lesen!

5 Stimmen

@AboozarRajabi Natürlich ist es möglich. Dieser Code kann jede Textdatei lesen.

14 Stimmen

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.

133voto

msayag Punkte 7878

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);
}

2 Stimmen

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.

3 Stimmen

Warum sollte man forEach() vermeiden? Ist es schlecht?

1 Stimmen

Wenn ich forEach anstelle von forEachOrdered verwende, werden die Zeilen möglicherweise nicht in der richtigen Reihenfolge gedruckt, oder?

40voto

DarkStar Punkte 535

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;
    }
}

1 Stimmen

Was bedeutet ein ByteArrayInputStream mit einem String-Literal gefüttert werden, mit dem Lesen einer großen Textdatei zu tun haben?

1 Stimmen

Absolut nutzlose Verschlüsse. Es gibt keinen Grund, jeden Stream zu schließen. Wenn Sie einen dieser Streams schließen, schließen Sie automatisch alle anderen Streams...

29voto

gomisha Punkte 2065

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 これ .

2 Stimmen

Ihr Führer ist erstaunlich :)

2 Stimmen

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.

0 Stimmen

Das stimmt. Vielleicht hätte ich diese Annahmen in meiner Antwort deutlicher machen sollen.

CodeJaeger.com

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.

Powered by:

X