Ich benutze die Redewendung unten schon seit einiger Zeit. Und es scheint am weitesten verbreitet zu sein, zumindest auf den Websites, die ich besucht habe.
Gibt es eine bessere / andere Möglichkeit, eine Datei in Java in eine Zeichenfolge einzulesen?
private String readFile(String file) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader (file));
String line = null;
StringBuilder stringBuilder = new StringBuilder();
String ls = System.getProperty("line.separator");
try {
while((line = reader.readLine()) != null) {
stringBuilder.append(line);
stringBuilder.append(ls);
}
return stringBuilder.toString();
} finally {
reader.close();
}
}
byte[] Files.readAllBytes(file);
Für diejenigen, die die einzeilige Scannerlösung vorschlagen: Müssen Sie sie nicht schließen?Antworten:
Lesen Sie den gesamten Text aus einer Datei
Java 11 hat die Methode readString () hinzugefügt , um kleine Dateien als Zeilenabschlusszeichen zu lesen
String
:Für Versionen zwischen Java 7 und 11 ist hier eine kompakte, robuste Sprache, die in einer Dienstprogrammmethode zusammengefasst ist:
Lesen Sie Textzeilen aus einer Datei
Java 7 hat eine bequeme Methode zum Lesen einer Datei als Textzeilen hinzugefügt , die als dargestellt wird
List<String>
. Dieser Ansatz ist "verlustbehaftet", da die Zeilentrennzeichen vom Ende jeder Zeile entfernt werden.Java 8 fügte die
Files.lines()
Methode hinzu , um a zu erzeugenStream<String>
. Auch diese Methode ist verlustbehaftet, da Zeilentrennzeichen entfernt werden. WennIOException
beim Lesen der Datei ein auftritt , wird es in ein eingeschlossenUncheckedIOException
, daStream
keine Lambdas akzeptiert werden, die geprüfte Ausnahmen auslösen.Dies
Stream
erfordert einenclose()
Anruf; Dies ist in der API schlecht dokumentiert, und ich vermute, dass viele Leute nicht einmal bemerken, dassStream
es eine gibtclose()
Methode gibt. Stellen Sie sicher, dass Sie wie gezeigt einen ARM-Block verwenden.Wenn Sie mit einer anderen Quelle als einer Datei arbeiten, können Sie die
lines()
Methode in verwendenBufferedReader
stattdessen verwenden.Speicherauslastung
Die erste Methode, bei der Zeilenumbrüche beibehalten werden, kann vorübergehend Speicherplatz benötigen, der um ein Vielfaches größer ist als die Datei, da für kurze Zeit der Inhalt der Rohdatei (ein Byte-Array) und die decodierten Zeichen (von denen jedes 16 Bit beträgt, selbst wenn es codiert ist) als 8 Bits in der Datei) befinden sich gleichzeitig im Speicher. Es ist am sichersten, auf Dateien anzuwenden, von denen Sie wissen, dass sie im Verhältnis zum verfügbaren Speicher klein sind.
Die zweite Methode, das Lesen von Zeilen, ist normalerweise speichereffizienter, da der Eingabebytepuffer zum Decodieren nicht die gesamte Datei enthalten muss. Es ist jedoch immer noch nicht für Dateien geeignet, die im Verhältnis zum verfügbaren Speicher sehr groß sind.
Zum Lesen großer Dateien benötigen Sie ein anderes Design für Ihr Programm, das einen Textblock aus einem Stream liest, verarbeitet und dann zum nächsten übergeht, wobei derselbe Speicherblock mit fester Größe wiederverwendet wird. Hier hängt "groß" von den Computerspezifikationen ab. Heutzutage kann dieser Schwellenwert viele Gigabyte RAM betragen. Die dritte Methode, a zu verwenden,
Stream<String>
ist eine Möglichkeit, dies zu tun, wenn Ihre eingegebenen "Datensätze" zufällig einzelne Zeilen sind. (Mit derreadLine()
Methode vonBufferedReader
ist das prozedurale Äquivalent zu diesem Ansatz.)Zeichenkodierung
Eine Sache, die im Beispiel im ursprünglichen Beitrag fehlt, ist die Zeichenkodierung. Es gibt einige Sonderfälle, in denen die Plattform standardmäßig Ihren Wünschen entspricht, diese sind jedoch selten und Sie sollten in der Lage sein, Ihre Wahl zu rechtfertigen.
Die
StandardCharsets
Klasse definiert einige Konstanten für die Codierungen, die für alle Java-Laufzeiten erforderlich sind:Die Plattformvorgabe ist in der
Charset
Klasse selbst verfügbar :Hinweis: Diese Antwort ersetzt weitgehend meine Java 6-Version. Das Dienstprogramm von Java 7 vereinfacht den Code sicher, und die alte Antwort, die einen zugeordneten Bytepuffer verwendete, verhinderte, dass die gelesene Datei gelöscht wurde, bis der zugeordnete Puffer mit Müll gesammelt wurde. Sie können die alte Version über den Link "Bearbeitet" zu dieser Antwort anzeigen.
quelle
FileChannel#map
im Allgemeinen unbrauchbar ist.Wenn Sie bereit sind, eine externe Bibliothek zu verwenden, lesen Sie Apache Commons IO (200 KB JAR). Es enthält eine
org.apache.commons.io.FileUtils.readFileToString()
Methode, mit der Sie ein Ganzes mit einer CodezeileFile
in eine lesen könnenString
.Beispiel:
quelle
Eine sehr schlanke Lösung basierend auf
Scanner
:Oder wenn Sie den Zeichensatz festlegen möchten:
Oder mit einem Try-with-Resources- Block, der
scanner.close()
Sie auffordert:Denken Sie daran, dass der
Scanner
Konstruktor ein werfen kannIOException
. Und vergessen Sie nicht , zu importierenjava.io
undjava.util
.Quelle: Pat Niemeyers Blog
quelle
java.util.NoSuchElementException
.seit java 7 kannst du es so machen.
quelle
Wenn Sie nach einer Alternative suchen, an der keine Bibliothek eines Drittanbieters beteiligt ist (z. B. Commons I / O ), können Sie die Scannerklasse verwenden :
quelle
Scanner scanner = new Scanner((Readable) new BufferedReader(new FileReader(file)));
. Andernfalls können Sie nur einen Teil der Datei erfassen.Guave hat eine ähnliche Methode wie Commons IOUtils, die Willi aus Rohr erwähnt hat:
EDIT by PiggyPiglet
Files#toString
ist veraltet und muss im Oktober 2019 entfernt werden. Verwenden Sie stattdessenFiles.asCharSource(new File(path), StandardCharsets.UTF_8).read();
EDIT von Oscar Reyes
Dies ist der (vereinfachte) zugrunde liegende Code in der zitierten Bibliothek:
Bearbeiten (von Jonik): Das Obige stimmt nicht mit dem Quellcode der neuesten Guava-Versionen überein. Die aktuelle Quelle finden Sie in den Klassen Dateien , CharStreams , ByteSource und CharSource im Paket com.google.common.io .
quelle
Closer
in CharSource . Der Code in der Antwort ist nicht die aktuelle Guava-Quelle........ .......
quelle
new String(Files.readAllBytes(FileSystems.getDefault().getPath( filename)));
new String(Files.readAllBytes(Paths.get(filename)));
:-)Paths
ist das Googeln anscheinend 1,7+ wie es istFileSystems
. (Dang it!)Wenn Sie eine Zeichenfolgenverarbeitung (Parallelverarbeitung) benötigen, verfügt Java 8 über die großartige Stream-API.
Weitere Beispiele finden Sie in JDK-Beispielen
sample/lambda/BulkDataOperations
, die von der Oracle Java SE 8-Downloadseite heruntergeladen werden könnenEin weiteres Beispiel für einen Einzeiler
quelle
Dieser Code normalisiert Zeilenumbrüche, die möglicherweise das sind, was Sie wirklich tun möchten oder nicht.
Hier ist eine Alternative, die das nicht tut und die (IMO) einfacher zu verstehen ist als der NIO-Code (obwohl er immer noch verwendet wird
java.nio.charset.Charset
):quelle
Sammelte alle möglichen Möglichkeiten, um die Datei als Zeichenfolge von der Festplatte oder vom Netzwerk zu lesen.
Guave: Google benutzt Klassen
Resources
,Files
APACHE - GEMEINSAME E / A mit den Klassen IOUtils, FileUtils
Java 8 BufferReader mit Stream API
Scannerklasse mit Regex
\A
. Dies entspricht dem Beginn der Eingabe.Java 7 (
java.nio.file.Files.readAllBytes
)BufferedReader
mitInputStreamReader
.Beispiel mit Hauptmethode für den Zugriff auf die oben genannten Methoden.
@sehen
quelle
Wenn es sich um eine Textdatei handelt, warum nicht Apache Commons-Io verwenden ?
Es hat die folgende Methode
Wenn Sie die Zeilen als Liste verwenden möchten, verwenden Sie
quelle
Seit JDK 11:
quelle
Eine Datei als Binärdatei lesen und am Ende konvertieren
quelle
Mit Java 7 ist dies meine bevorzugte Option zum Lesen einer UTF-8-Datei:
Seit Java 7 verfügt das JDK über die neue
java.nio.file
API, die viele Verknüpfungen bietet, sodass Bibliotheken von Drittanbietern für einfache Dateivorgänge nicht immer erforderlich sind.quelle
Java versucht, in allem, was es tut, extrem allgemein und flexibel zu sein. Infolgedessen ist etwas, das in einer Skriptsprache relativ einfach ist (Ihr Code würde
open(file).read()
in Python durch " " ersetzt), viel komplizierter. Es scheint keinen kürzeren Weg zu geben, als eine externe Bibliothek zu verwenden (wie Willi aus Rohr erwähnt hat). Deine Optionen:Ihre beste Wette ist wahrscheinlich die 2., da sie die geringsten Abhängigkeiten aufweist.
quelle
byte[] bytes = Files.readAllBytes(someFile.toPath());
Verwenden von JDK 8 oder höher:
Keine externen Bibliotheken verwendet
Sie können ein neues String-Objekt aus dem Dateiinhalt erstellen (Verwenden von Klassen aus dem
java.nio.file
Paket):quelle
Es gibt eine Variation desselben Themas, bei der anstelle einer while-Schleife eine for-Schleife verwendet wird, um den Umfang der Zeilenvariablen einzuschränken. Ob es "besser" ist, ist eine Frage des persönlichen Geschmacks.
quelle
line
Variablen eingeschränkt werden sollte. Die Bearbeitung hat es zweimal deklariert, was ein Kompilierungsfehler wäre.Wenn Sie keinen Zugriff auf die
Files
Klasse haben, können Sie eine native Lösung verwenden.quelle
Eine flexible Lösung mit IOUtils von Apache commons-io in Kombination mit StringWriter :
Es funktioniert mit jedem Reader oder Eingabestream (nicht nur mit Dateien), beispielsweise beim Lesen von einer URL.
quelle
Beachten Sie, dass bei Verwendung
fileInputStream.available()
der zurückgegebenen Ganzzahl nicht die tatsächliche Dateigröße angegeben werden muss, sondern die geschätzte Anzahl von Bytes, die das System aus dem Stream lesen kann, ohne die E / A zu blockieren. Ein sicherer und einfacher Weg könnte so aussehenEs sollte berücksichtigt werden, dass dieser Ansatz nicht für Mehrbyte-Zeichencodierungen wie UTF-8 geeignet ist.
quelle
available()
Methode gibt es keine Garantie dafür, dass das Dateiende erreicht ist, falls die Methode 0 zurückgibt. In diesem Fall erhalten Sie möglicherweise eine unvollständige Datei. Was noch schlimmer ist, die Anzahl der tatsächlich gelesenen Bytes kann kleiner sein als der von zurückgegebene Wertavailable()
. In diesem Fall erhalten Sie eine beschädigte Ausgabe.Dieser verwendet die Methode
RandomAccessFile.readFully
, sie scheint ab JDK 1.0 verfügbar zu sein!quelle
Sie können Scanner- und Dateiklasse ausprobieren, eine Lösung mit wenigen Zeilen
quelle
Benutzer
java.nio.Files
, um alle Zeilen der Datei zu lesen.quelle
quelle
cannot find symbol
.Ich kann noch keine anderen Einträge kommentieren, also lasse ich es einfach hier.
Eine der besten Antworten hier ( https://stackoverflow.com/a/326448/1521167 ):
hat noch einen Fehler. Es wird immer ein neues Zeilenzeichen am Ende des Strings eingefügt, was einige seltsame Fehler verursachen kann. Mein Vorschlag ist, es zu ändern in:
quelle
Nach Strg + F'ing nach Scanner denke ich, dass die Scannerlösung auch aufgelistet werden sollte. Auf die am einfachsten zu lesende Weise geht es so:
Wenn Sie Java 7 oder höher verwenden (und dies sollten Sie wirklich tun), sollten Sie Try-with-Resources verwenden, um das Lesen des Codes zu vereinfachen. Kein punktnahes Zeug mehr, das alles verschmutzt. Aber das ist meistens eine stilistische Entscheidung.
Ich poste dies hauptsächlich aus Gründen der Vervollständigung, denn wenn Sie dies häufig tun müssen, sollte es Dinge in java.nio.file.Files geben , die die Arbeit besser machen sollten.
Mein Vorschlag wäre, Files # readAllBytes (Path) zu verwenden, um alle Bytes zu erfassen und sie einem neuen String (byte [] Charset) zuzuführen. , um einen String daraus zu erhalten, dem Sie vertrauen können. Charsets werden für Sie während Ihres Lebens gemein sein, also hüten Sie sich jetzt vor diesem Zeug.
Andere haben Code und so gegeben, und ich möchte ihren Ruhm nicht stehlen. ;)
quelle
Bei Verwendung dieser Bibliothek handelt es sich um eine Zeile:
quelle
Auch wenn sich Ihre Datei in einem Glas befindet, können Sie Folgendes verwenden:
Der Pfad sollte
/
zum Beispiel mit beginnen, wenn Ihr Glas istDann möchten Sie es so aufrufen:
quelle
In einer Zeile (Java 8), vorausgesetzt, Sie haben einen Reader:
quelle
Basierend auf der Antwort von @ erickson können Sie Folgendes verwenden:
quelle