In der Vergangenheit war die Eingabe- / Ausgabeverarbeitung von Java als umständlich bekannt. Die Verarbeitung der Eingabe / Ausgabe von Dateien in Java war häufig das Ziel von Angriffen, als das Skript-Sprachcamp seine hohe "Produktivität" ansprach. Es wird gesagt, dass die Verarbeitung, die in wenigen Zeilen in einer Skriptsprache realisiert werden kann, in Java zu Dutzenden von Zeilen wird.
Die Zeit ist vergangen und die Situation hat sich mit dem 2011 in Java 7 eingeführten Paket "java.nio.file" (NIO2 File API) und der Try-with-Resources-Syntax erheblich verbessert. Jetzt kann sogar Java die Verarbeitung von Dateieingaben / -ausgaben mit der gleichen Codemenge wie die Skriptsprache realisieren.
In Artikeln, die nach "Eingabe / Ausgabe von Java-Dateien" suchen und ganz oben stehen, fällt jedoch nur unangemessener Code auf, der nur die API verwendet, bevor die oben genannten Verbesserungen eingeführt wurden. Daher möchte ich in diesem Artikel die einfachste Eingabe- / Ausgabeverarbeitung für Java-Dateien, die Anfänger derzeit kennen sollten, systematisch und präzise zusammenfassen, unabhängig vom historischen Hintergrund der Vergangenheit.
Die Schnittstelle java.nio.file.Path
(Referenz: Javadoc wird verwendet, um den Pfad des Dateisystems darzustellen. /Path.html)) wird verwendet. Es gibt verschiedene Möglichkeiten, eine Pfadinstanz zu erstellen, aber in Wirklichkeit die Dienstprogrammklasse "java.nio.file.Paths" (Referenz: Javadoc Meistens generiert mit java / nio / file / Paths.html)).
Path path = Paths.get("items.csv");
Sie können die Pfadzeichenfolge entweder als relativen oder als absoluten Pfad angeben.
Path path = Paths.get("/etc/passwd");
In Anbetracht der Art der Portabilität von durch Pfade getrennten Zeichenfolgen ist es besser, diese Argumentmethode mit variabler Länge zu verwenden.
Path path = Paths.get("/etc", "passwd");
Ab Java 11 wurde zusätzlich zur Methode Paths.get (String) die Methode Path.of (String)
eingeführt (Referenz: Javadoc. javase / 11 / docs / api / java.base / java / nio / file / Path.html # von (java.lang.String, java.lang.String ...))). Die Funktion ist dieselbe, aber diese ist konsistenter mit "List.of ()" "Map.of ()" usw., die ebenfalls in Java 11 eingeführt wurde, und ist natürlich.
Path path = Path.of("items.csv");
Die dateibezogene Verarbeitung erfolgt über die Schnittstelle "Path" und die Dienstprogrammklasse "java.nio.file.Files" (Referenz: Javadoc. Kombiniere nio / file / Files.html)). Zum Beispiel sieht es so aus.
List<String> lines = Files.readAllLines(Paths.get("items.csv"));
Die Klasse, die eine Datei in Java darstellt, ist "java.io.File" (Referenz: Javadoc. )) Du könntest daran denken. Dies ist eine ältere Methode und kann durch die Funktionalität des Pakets java.nio.file
ersetzt werden. Beachten Sie, dass Sie zwischen "Path # toFile ()" und "File # toPath ()" konvertieren können, wenn die alte API nur "java.io.File" anstelle von "java.nio.file.Path" akzeptiert.
In diesem Artikel werden wir nicht auf die Details einer Textbinärdatei eingehen, sondern einfach Dateien vom Typ "String" aus Javas Sicht lesen und schreiben, die als Textdateien bezeichnet werden.
Der einfachste Weg, Text zu lesen, ist die Methode "Files.readString (Path)". Diese Methode gibt den gesamten Inhalt der Datei als String zurück.
String content = Files.readString(Paths.get("items.csv"));
Sie müssen beim Lesen und Schreiben von Text auf den Zeichensatz achten. Der obige Code gibt keinen Zeichensatz an, daher wird der Standard-UTF-8 verwendet. Die Methode zur Angabe des Zeichensatzes ist unten dargestellt.
String content = Files.readString(Paths.get("items.csv"), StandardCharsets.UTF_8);
String content = Files.readString(Paths.get("items.csv"), Charset.forName("MS932"));
Nun, hier ist eine unglückliche Nachricht. Die oben beschriebene Methode "Files.readString (Path)" "Files.readString (Path, Charset)" ist nur in Java 11 und höher verfügbar. Hier ist eine andere Möglichkeit, wie Sie es von Java 7 aus verwenden können. Diese Methode gibt den Inhalt der Datei als Typ "List
List<String> lines = Files.readAllLines(Paths.get("items.csv"), StandardCharsets.UTF_8);
Wenn die Dateigröße klein ist, können Sie sie alle wie oben beschrieben gleichzeitig lesen. Wenn Sie jedoch die Möglichkeit haben, Dateien zu verarbeiten, die größer als zehn oder Hunderte von Megabyte sind, sollten Sie sich daran erinnern, wie Sie hier mit "Stream
try (Stream<String> lines = Files.lines(Paths.get("items.csv"), StandardCharsets.UTF_8)) {
lines.forEach(line -> System.out.println(line));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
Verwenden Sie bei Verwendung dieser Methode die Syntax "Try-with-Resources", um zu verhindern, dass das Schließen vergessen wird. Gleiches gilt für das Lesen und Schreiben anderer Unterteilungen. Weitere Informationen finden Sie unter Schrittweises Verständnis der Behandlung von Java-Ausnahmen.
Wenn Sie unterteilten Text lesen müssen, der nicht zeilenorientiert ist, wird "java.io.BufferedReader" von "Files.newBufferedReader (Path, Charset)" zurückgegeben (Referenz: Javadoc Verwenden Sie com / javase / jp / 8 / docs / api / java / io / BufferedReader.html)). Wenn Sie eine große JSON-Datei ohne Zeilenumbrüche lesen möchten, benötigen Sie diese Methode.
try (BufferedReader in = Files.newBufferedReader(Paths.get("items.csv"), StandardCharsets.UTF_8)) {
for (int ch = 0; (ch = in.read()) > 0;) {
System.out.print((char) ch);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
Weitere Abstraktion in Kombination mit java.util.Scanner
(Referenz: Javadoc) High API kann verwendet werden.
try (BufferedReader in = Files.newBufferedReader(Paths.get("items.csv"), StandardCharsets.UTF_8);
Scanner sc = new Scanner(in)) {
sc.useDelimiter("(,|\\n)");
while (sc.hasNext()) {
System.out.println(sc.next());
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
Der einfachste Weg, Text zu schreiben, ist die Methode Files.writeString (Path, CharSequence, OpenOption ...)
. Diese Methode schreibt den gesamten Inhalt der angegebenen "CharSequence" in eine Datei. Außerdem sind "String" und "StringBuilder" eine Art "CharSequence" (Referenz: Javadoc. html)).
String content = "0-0\t0-1\t0-2\n1-0\t1-1\t1-2\n";
Files.writeString(Paths.get("items.tsv"), content);
Sie können es hinzufügen, indem Sie "OpenOption" einstellen.
String content = "0-0\t0-1\t0-2\n1-0\t1-1\t1-2\n";
Files.writeString(Paths.get("items.tsv"), content, StandardOpenOption.APPEND);
Sie können den Zeichensatz sowohl hier als auch beim Lesen angeben.
String content = "0-0\t0-1\t0-2\n1-0\t1-1\t1-2\n";
Files.writeString(Paths.get("items.tsv"), content, StandardCharsets.UTF_8);
String content = "0-0\t0-1\t0-2\n1-0\t1-1\t1-2\n";
Files.writeString(Paths.get("items.tsv"), content, Charset.forName("MS932"));
Hier ist eine weitere unglückliche Nachricht. Die obige Methode "Files.writeString (Pfad, CharSequence, OpenOption ...)" "Files.writeString (Pfad, CharSequence, Zeichensatz, OpenOption ...)" ist nur in Java 11 und höher verfügbar. Vorher können Sie nur die gleiche Methode anwenden wie beim Schreiben in kleinen Stücken.
Beim Schreiben von Text in kleinen Stücken wurde "java.io.BufferedWriter" von "Files.newBufferedWriter (Pfad, Zeichensatz, OpenOption ...)" zurückgegeben (Referenz: Javadoc /jp/8/docs/api/java/io/BufferedWriter.html)) wird verwendet.
List<String> lines = new ArrayList<String>();
...
try (BufferedWriter out = Files.newBufferedWriter(Paths.get("items.tsv"), StandardCharsets.UTF_8)) {
for (String line : lines) {
out.write(line);
out.newLine();
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
In diesem Artikel wird eine Datei, die aus Java-Sicht einfach als Byte-Zeichenfolge gelesen und geschrieben wird, als Binärdatei bezeichnet.
Der einfachste Weg, eine Binärdatei zu lesen, ist die Methode "Files.readBytes (Path)". Diese Methode gibt den gesamten Inhalt der Datei als "byte []" zurück.
byte[] content = Files.readAllBytes(Paths.get("selfie.jpg "));
Als Referenz wird unten die Methode zum Konvertieren von "byte []" in "String" oder "java.io.InputStream" gezeigt. Eine solche Konvertierung ist abhängig von der Benutzerfreundlichkeit der API erforderlich, an die die geladene Binärdatei übergeben wird.
byte[] content = Files.readAllBytes(Paths.get("items.csv"));
String contentAsString = new String(content, StandardCharsets.UTF_8);
byte[] content = Files.readAllBytes(Paths.get("selfie.jpg "));
InputStream in = new ByteArrayInputStream(content);
Wie bei Text wird das Laden in großen Mengen für große Dateien nicht empfohlen. Stattdessen gibt die Methode "Files.newInputStream (Path, OpenOption ...)" "java.io.InputStream" zurück (Referenz: Javadoc Verwenden Sie /api/java/io/InputStream.html)). In Bezug auf den erworbenen java.io.InputStream
gibt es mehr Fälle, in denen er von einer vorhandenen Bibliothek verarbeitet wird, als wenn er durch Drehen einer eigenen Schleife verarbeitet wird. Der folgende Code übergibt ihn beispielsweise an Apache POI.
try (InputStream in = Files.newInputStream(Paths.get("items.xlsx"))) {
XSSFWorkbook book = new XSSFWorkbook(in);
...
} catch (IOException e) {
throw new UncheckedIOException(e);
}
Der einfachste Weg, eine Binärdatei zu schreiben, ist die Methode Files.write (Path, byte [], OpenOption ...)
.
byte[] content = ...;
Files.write(Paths.get("selfie.jpg "), content);
Beim Schreiben einer Binärdatei in kleinen Stücken wird "java.io.OutputStream" von "Files.newOutputStream (Path, OpenOption ...)" zurückgegeben (Referenz: Javadoc / 8 / docs / api / java / io / OutputStream.html))) wird verwendet. Es wird mehr Fälle geben, in denen die vorhandene Bibliothek dies ebenfalls behandelt, anstatt es selbst zu erledigen. Der folgende Code übergibt ihn beispielsweise an Apache POI.
Item item = ...;
try (OutputStream out = Files.newOutputStream(Paths.get("items.xlsx"))) {
XSSFWorkbook book = new XSSFWorkbook();
...
book.write(out);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
Im Folgenden finden Sie ein Beispiel für Code, der in Zeiten üblich war, in denen es weder eine NIO2-Datei-API noch einen Versuch mit Ressourcen gab. Dies ist sicherlich eine Komplexität, die nicht beanstandet werden kann, selbst wenn sie vom Skript-Sprachcamp angegriffen wird. In Bezug auf den Teil, der ein mehrstufiger Try-Catch ist: "Wenn Sie" BufferedReader "schließen, wird auch der untere" InputStream "geschlossen. Wenn Sie" BufferedReader "jedoch nicht initialisieren, kann ein Ressourcenleck auftreten. Ich erinnere mich, dass es ein Argument wie "Es ist notwendig für ..." gab. Ich habe die Details vergessen und glaube nicht, dass ich mich mehr an sie erinnern muss.
String content = null;
InputStream is = null;
try {
is = new FileInputStream("items.csv");
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line);
sb.append(System.lineSeparator());
}
content = sb.toString();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
} catch (IOException e) {
new RuntimeException(e);
} finally {
try {
if (is != null) {
is.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Was Sie mit dem obigen Code versuchen, können Sie jetzt wieder erreichen mit:
String content = Files.readString(Paths.get("items.csv"));
Recommended Posts