Alle Texte aus einer Datei lesen
In Java 11 wurde die readString()-Methode hinzugefügt, um kleine Dateien als String
zu lesen und Zeilenenden beizubehalten:
String inhalt = Files.readString(pfad, codierung);
Für Versionen zwischen Java 7 und 11 bietet sich hier ein kompakter, robuster Idiom, eingebettet in einer Hilfsmethode:
static String dateiLesen(String pfad, Charset codierung)
throws IOException
{
byte[] codiert = Files.readAllBytes(Paths.get(pfad));
return new String(codiert, codierung);
}
Linien mit Text aus einer Datei lesen
In Java 7 wurde eine Bequemlichkeitsmethode hinzugefügt, um eine Datei als Textzeilen zu lesen, dargestellt als eine List
. Dieser Ansatz ist "verlustbehaftet", da die Zeilenumbrüche am Ende jeder Zeile entfernt werden.
List zeilen = Files.readAllLines(Paths.get(pfad), codierung);
In Java 8 wurde die Files.lines()
-Methode hinzugefügt, um einen Stream
zu erzeugen. Auch diese Methode entfernt Zeilenumbrüche. Wenn während des Dateilesevorgangs ein IOException
auftritt, wird es in eine UncheckedIOException
eingepackt, da Stream
keine Lambdas akzeptiert, die überprüfbare Ausnahmen werfen.
try (Stream zeilen = Files.lines(pfad, codierung)) {
zeilen.forEach(System.out::println);
}
Dieser Stream
benötigt einen close()
-Aufruf; dies ist in der API schlecht dokumentiert, und ich vermute, dass viele Leute nicht einmal bemerken, dass Stream
eine close()
-Methode hat. Stellen Sie sicher, dass Sie einen ARM-Block wie gezeigt verwenden.
Wenn Sie mit einer Quelle arbeiten, die nicht eine Datei ist, können Sie die lines()
-Methode in BufferedReader
verwenden.
Speicherauslastung
Wenn Ihre Datei im Vergleich zu Ihrem verfügbaren Speicher klein genug ist, könnte das Lesen der gesamten Datei auf einmal gut funktionieren. Ist Ihre Datei jedoch zu groß, könnte es besser sein, eine Zeile nach der anderen zu lesen, zu verarbeiten und dann zu verwerfen, bevor Sie zur nächsten übergehen. Das Stream-Verarbeiten auf diese Weise kann die Gesamtgröße der Datei als Faktor für Ihren Speicherbedarf beseitigen.
Zeichenkodierung
Etwas, das im Beispiel im Originalbeitrag fehlt, ist die Zeichenkodierung. Diese Kodierung kann im Allgemeinen nicht aus der Datei selbst bestimmt werden und erfordert Metadaten wie einen HTTP-Header, um diese wichtige Information zu übermitteln.
Die Klasse StandardCharsets
definiert einige Konstanten für die Kodierungen, die von allen Java-Laufzeiten benötigt werden:
String inhalt = dateiLesen("test.txt", StandardCharsets.UTF_8);
Das plattformspezifische Standardenkodierung ist über die Klasse Charset
selbst verfügbar:
String inhalt = dateiLesen("test.txt", Charset.defaultCharset());
Es gibt einige spezielle Fälle, in denen das plattformspezifische Standardverhalten angemessen ist, aber sie sind selten. Sie sollten Ihre Wahl begründen können, da das plattformspezifische Standardverhalten nicht portabel ist. Ein Beispiel, wo es richtig sein könnte, ist beim Lesen von Standardinput oder Schreiben von Standardausgabe.
Hinweis: Diese Antwort ersetzt größtenteils meine Java 6-Version. Die Nützlichkeit von Java 7 vereinfacht den Code sicher, und die alte Antwort, die einen zugeordneten Byte-Buffer verwendete, verhinderte, dass die gelesene Datei gelöscht wurde, bis der zugeordnete Buffer vom Garbage-Collector gesammelt wurde. Sie können die alte Version über den "bearbeitet" Link in dieser Antwort anzeigen.
8 Stimmen
Kann mir jemand auf eine sehr einfache Weise erklären, was es mit dem NIO auf sich hat? Jedes Mal, wenn ich darüber lese, verliere ich mich in der x-ten Erwähnung eines Kanals :(
8 Stimmen
Bitte beachten Sie, dass nicht garantiert ist, dass der Zeilentrenner in der Datei derselbe ist wie der Zeilentrenner des Systems.
7 Stimmen
Der obige Code hat einen Fehler, bei dem ein zusätzliches Zeilenumbruchzeichen in der letzten Zeile hinzugefügt wird. Es sollte etwas Ähnliches wie folgt sein: if ( (line = reader.readLine()) != null) { stringBuilder.append( line ); } while ( (line = reader.readLine()) != null) { stringBuilder.append( ls ); stringBuilder.append( line ); }
32 Stimmen
Java 7 führt
byte[] Files.readAllBytes(file);
ein. An diejenigen, die die 'einzeilige' Scanner-Lösung vorschlagen: Muss man es nicht schließen?0 Stimmen
@OscarRyz Der größte Unterschied für mich ist, dass NIO es ermöglicht, auf viele Ports zu hören, ohne einen Thread für jeden zuzuweisen. Kein Problem, es sei denn, Sie möchten ein Paket an jede Maschine im Adressraum eines Klasse-B-Netzwerks senden (65.000 Adressen), um zu sehen, was existiert. Windows läuft bei ungefähr 20.000 Threads aus (Habe dies herausgefunden, als ich genau dieses Problem gelöst habe - Entdeckung eines Klasse-A/B-Netzwerks, bevor es NIO gab, war es schwierig).
0 Stimmen
Wenn Sie die Files.readAllBytes() Implementierung sehen, werden Sie feststellen, dass sie einen kanal verwendet, der schließbar ist. Es ist also nicht erforderlich, ihn explizit zu schließen.
0 Stimmen
Mit der Einführung von Groovy können Sie die Datei so lesen: return new File( file).text()
0 Stimmen
Verknüpfen Sie einen anderen StackOverflow-Link, der gut erklärt ist: stackoverflow.com/questions/14169661/…
0 Stimmen
@Deep Die letzte Zeile in einer Textdatei ist normalerweise zeilenbeendet, daher ist das, was Sie als Fehler beschreiben, keiner, und Ihr Code hat den Fehler, alle Zeilentrennzeichen zu entfernen.
0 Stimmen
Bitte akzeptiere eine Antwort auf deine Frage und hilf dabei, dies zu klären.
0 Stimmen
An all jene armen Seelen, die Byte-basierte Methoden empfehlen, wenn offensichtlich Text behandelt werden sollte: Unsere Welt wird die Hölle sein, solange du in deiner Unwissenheit beharrst. (Ich meine, ich bin nachsichtig mit Code aus den 90ern in dieser Hinsicht, aber verdamm nochmal, wir sind im Jahr 2021, und Globalisierung und Nicht-ASCII-Zeichen sind etwas.)
0 Stimmen
@FranzD. Was denken Sie, wird verwendet, um diesen Text in einer Datei zu speichern?
0 Stimmen
@OscarRyz: Nun, Bytes, mein lieber Oscar. Aber byte-basierte Methoden neigen dazu, die Feinheiten der Byte <-> Zeichenkonvertierungen nicht angemessen zu behandeln. Und obwohl das funktionieren könnte, wenn du deinen Code mit ASCII oder vielleicht sogar Latin-1 testest, wird es furchtbar scheitern und Stunden an Arbeit und Frustration verursachen, sobald jemand versucht, Chinesisch oder eine andere "kleine" (in IHRER Welt) Sprache zu lesen/schreiben. Die meisten meiner ehemaligen Kollegen, die stolz sich "Software-Ingenieure" nannten, kannten weder noch interessierten sie sich für UTF-16-Ersatzzeichen, und ja, ich nenne das ignorant, weil das ist es.
0 Stimmen
@Franz D. Gut, dann lesen Sie Bytes und entschlüsseln sie unter Verwendung der geeigneten Zeichenkodierung. Sie nehmen fälschlicherweise an, dass die Datei in UTF-16 codiert wäre, aber sie könnte buchstäblich alles andere sein. Es wird dringend empfohlen, heute alles in UTF-8 zu verwenden. Lesen Sie die akzeptierte Antwort, sie enthält sehr nützliche Informationen.