Java-Streams, Dateien und E/A
Streams, Dateien und IO (Eingabe/Ausgabe) in Java sind die Infrastruktur für das Lesen und Schreiben von Daten. Sie ermöglichen Programmen die Interaktion mit externen Daten (wie Dateien, Netzwerken, Systemeingabe usw.).
Das Paket java.io ist ein Kernpaket in der Java-Standardbibliothek und stellt Klassen für Systemeingabe und -ausgabe bereit. Es enthält Werkzeuge für die Verarbeitung von Datenströmen (Byte-Streams und Zeichenströme), Lesen und Schreiben von Dateien, Serialisierung und Datenformatierung.
java.io ist das grundlegende Paket für die Behandlung von Dateioperationen, Stream-Operationen und Low-Level-IO-Operationen.
Die Streams im Paket java.io unterstützen viele Formate, wie primitive Typen, Objekte, lokalisierte Zeichensätze und so weiter.
Ein Stream kann als eine Folge von Daten verstanden werden. Ein Eingabestream steht für das Lesen von Daten aus einer Quelle, und ein Ausgabestream steht für das Schreiben von Daten an ein Ziel.
Konsoleneingabe lesen
Die Java-Konsoleneingabe wird von System.in behandelt.
Um einen an die Konsole gebundenen Zeichenstrom zu erhalten, können Sie System.in in ein BufferedReader-Objekt einwickeln, um einen Zeichenstrom zu erstellen.
Das Folgende ist die grundlegende Syntax zum Erstellen eines BufferedReader:
Nachdem das BufferedReader-Objekt erstellt wurde, können wir die read()-Methode verwenden, um ein Zeichen von der Konsole zu lesen, oder die readLine()-Methode, um eine Zeichenkette zu lesen.
Mehrere Zeichen aus der Konsoleneingabe lesen
Um ein Zeichen aus einem BufferedReader-Objekt zu lesen, verwenden Sie die read()-Methode. Ihre Syntax lautet wie folgt:
Jedes Mal, wenn die read()-Methode aufgerufen wird, liest sie ein Zeichen aus dem Eingabestrom und gibt das Zeichen als Ganzzahlwert zurück. Sie gibt -1 zurück, wenn der Strom endet. Diese Methode wirft eine IOException.
Das folgende Programm demonstriert die Verwendung der read()-Methode, um kontinuierlich Zeichen von der Konsole zu lesen, bis der Benutzer eingibtq。
Code der Datei BRRead.java:
Das Kompilierungs- und Ausführungsergebnis des obigen Beispiels ist wie folgt:
输入字符, 按下 'q' 键退出。 example r u n o o b q q
Strings aus der Konsoleneingabe lesen
Um einen String aus der Standardeingabe zu lesen, müssen Sie die Methode readLine() von BufferedReader verwenden.
Das allgemeine Format lautet:
Das folgende Programm liest und zeigt Zeichenzeilen an, bis Sie das Wort "end" eingeben.
Code der Datei BRReadLines.java:
Das Kompilierungs- und Ausführungsergebnis des obigen Beispiels ist wie folgt:
Enter lines of text. Enter 'end' to quit. This is line one This is line one This is line two This is line two end end
In Versionen nach JDK 5 können wir auch dieJava ScannerKlasse verwenden, um Konsoleneingabe zu erhalten.
Konsolenausgabe
Wie bereits erwähnt, erfolgt die Konsolenausgabe durch print() und println(). Diese Methoden sind alle in der Klasse PrintStream definiert, und System.out ist eine Referenz auf ein Objekt dieser Klasse.
PrintStream erbt von der Klasse OutputStream und implementiert die Methode write(). Somit kann write() auch verwendet werden, um in die Konsole zu schreiben.
Die einfachste von PrintStream definierte Form von write() lautet wie folgt:
Diese Methode schreibt die niederwertigen acht Bits von byteval in den Stream.
Beispiel
Das folgende Beispiel verwendet write(), um das Zeichen "A" gefolgt von einem Zeilenumbruch auf dem Bildschirm auszugeben:
Code der Datei WriteDemo.java:
Beim Ausführen des obigen Beispiels wird das Zeichen "A" im Ausgabefenster ausgegeben.
A
Hinweis:Die Methode write() wird nicht häufig verwendet, weil die Methoden print() und println() bequemer zu verwenden sind.
Dateien lesen und schreiben
Wie bereits erwähnt, ist ein Stream als Datenfolge definiert. Eingabestreams werden verwendet, um Daten aus einer Quelle zu lesen, und Ausgabestreams werden verwendet, um Daten an ein Ziel zu schreiben.
Das folgende Diagramm ist ein Klassenhierarchiediagramm, das Eingabe- und Ausgabestreams beschreibt.
Byte-Streams (Verarbeitung binärer Daten)
Byte-Streams werden verwendet, um binäre Daten wie Dateien, Bilder, Videos usw. zu verarbeiten.
| Klassenname | Type | Beschreibung |
|---|---|---|
InputStream | Abstrakte Klasse (Eingabestream) | Die Oberklasse aller Byte-Eingabestreams, die Byte-Eingabeoperationen verarbeitet. |
OutputStream | Abstrakte Klasse (Ausgabestream) | Die Oberklasse aller Byte-Ausgabestreams, die Byte-Ausgabeoperationen verarbeitet. |
FileInputStream | Eingabestream | Liest Byte-Daten aus einer Datei. |
FileOutputStream | Ausgabestream | Schreibt Byte-Daten in eine Datei. |
BufferedInputStream | Eingabestream | Bietet Pufferung für Byte-Eingabestreams, um die Leseeffizienz zu verbessern. |
BufferedOutputStream | Ausgabestream | Bietet Pufferung für Byte-Ausgabestreams, um die Schreibeffizienz zu verbessern. |
ByteArrayInputStream | Eingabestream | Verwendet ein Byte-Array im Speicher als Eingabequelle. |
ByteArrayOutputStream | Ausgabestream | Schreibt Daten in ein Byte-Array im Speicher. |
DataInputStream | Eingabestream | Ermöglicht das Lesen primitiver Java-Datentypen aus einem Eingabestream (wie z. B.int、float、boolean)。 |
DataOutputStream | Ausgabestream | Ermöglicht das Schreiben primitiver Java-Datentypen in einen Ausgabestream. |
ObjectInputStream | Eingabestream | Liest serialisierte Objekte aus einem Eingabestream. |
ObjectOutputStream | Ausgabestream | Serialisiert Objekte und schreibt sie in einen Ausgabestream. |
PipedInputStream | Eingabestream | Wird verwendet, um Byte-Daten in einer Pipe zu lesen, normalerweise mitPipedOutputStreamWird zusammen verwendet. |
PipedOutputStream | Ausgabestream | Wird verwendet, um Byte-Daten in einer Pipe zu schreiben, normalerweise mitPipedInputStreamWird zusammen verwendet. |
FilterInputStream | Eingabestream | Eine Wrapper-Klasse für Byte-Eingabestreams, die zum Filtern anderer Eingabestreams verwendet wird. |
FilterOutputStream | Ausgabestream | Eine Wrapper-Klasse für Byte-Ausgabestreams, die zum Filtern anderer Ausgabestreams verwendet wird. |
SequenceInputStream | Eingabestream | Kombiniert mehrere Eingabestreams zu einem Eingabestream zur Verarbeitung. |
Zeichenströme (Verarbeitung von Textdaten)
Zeichenströme werden verwendet, um Textdaten zu verarbeiten, z. B. zum Lesen und Schreiben von Zeichenfolgen oder Dateien.
| Klassenname | Type | Beschreibung |
|---|---|---|
Reader | Abstrakte Klasse (Eingabestream) | Die Oberklasse aller Zeichen-Eingabestreams, die Zeicheneingabeoperationen verarbeitet. |
Writer | Abstrakte Klasse (Ausgabestream) | Die Oberklasse aller Zeichenausgabeströme, die Zeichenausgabeoperationen verarbeitet. |
FileReader | Eingabestream | Liest Zeichendaten aus einer Datei. |
FileWriter | Ausgabestream | Schreibt Zeichendaten in eine Datei. |
BufferedReader | Eingabestream | Bietet Pufferung für Zeicheneingabeströme, unterstützt zeilenweises Lesen und verbessert die Leseeffizienz. |
BufferedWriter | Ausgabestream | Bietet Pufferung für Zeichenausgabeströme, unterstützt zeilenweises Schreiben und verbessert die Schreibeffizienz. |
CharArrayReader | Eingabestream | Verwendet ein Zeichenarray als Eingabequelle. |
CharArrayWriter | Ausgabestream | Schreibt Daten in ein Zeichenarray. |
StringReader | Eingabestream | Verwendet eine Zeichenkette als Eingabequelle. |
StringWriter | Ausgabestream | Schreibt Daten in einen Zeichenkettenpuffer. |
PrintWriter | Ausgabestream | Komfortabler Zeichenausgabestrom, unterstützt Auto-Flush und formatierte Ausgabe. |
PipedReader | Eingabestream | Wird verwendet, um Zeichendaten in einer Pipe zu lesen, normalerweise mitPipedWriterzusammen verwendet. |
PipedWriter | Ausgabestream | Wird verwendet, um Zeichendaten in eine Pipe zu schreiben, normalerweise mitPipedReaderzusammen verwendet. |
LineNumberReader | Eingabestream | Gepufferter Zeichen-Eingabestream mit Zeilennummern, der das Verfolgen der gerade gelesenen Zeilennummer ermöglicht. |
PushbackReader | Eingabestream | Ermöglicht das Zurückschieben von Zeichen in den Stream nach dem Lesen, sodass sie erneut gelesen werden können. |
Hilfsklassen (weitere wichtige Klassen)
Hilfsklassen bieten Unterstützung für Dateien, Verzeichnisse und wahlfreien Dateizugriff.
| Klassenname | Type | Beschreibung |
|---|---|---|
File | Datei- und Verzeichnisoperationen | Wird verwendet, um eine Datei oder ein Verzeichnis darzustellen, und bietet Dateioperationen wie Erstellen, Löschen, Umbenennen usw. |
RandomAccessFile | Datei mit wahlfreiem Zugriff | Unterstützt wahlfreien Zugriff auf Dateien, sodass Daten an jeder beliebigen Position in der Datei gelesen und geschrieben werden können. |
Console | Konsolen-Eingabe/Ausgabe | Bietet Eingabe- und Ausgabeunterstützung für die Systemkonsole. |
Die beiden wichtigen Streams, die als Nächstes besprochen werden, sindFileInputStreamundFileOutputStream。
FileInputStream
Dieser Stream wird verwendet, um Daten aus einer Datei zu lesen. Sein Objekt kann mit dem Schlüsselwort new erstellt werden.
Es gibt mehrere Konstruktoren, die zum Erstellen von Objekten verwendet werden können.
Sie können einen Dateinamen vom Typ String verwenden, um ein Eingabestreamobjekt zum Lesen einer Datei zu erstellen:
Sie können auch ein Dateiobjekt verwenden, um ein Eingabestreamobjekt zum Lesen einer Datei zu erstellen. Zuerst müssen wir die Methode File() verwenden, um ein Dateiobjekt zu erstellen:
Sobald das InputStream-Objekt erstellt wurde, können Sie die folgenden Methoden verwenden, um den Stream zu lesen oder andere Stream-Operationen auszuführen.
| Methode | Beschreibung | Beispielcode |
|---|---|---|
int read() | Liest ein Byte Daten, wobei der Rückgabewert eine Ganzzahl zwischen 0 und 255 ist. Gibt -1 zurück, wenn das Ende des Streams erreicht ist. | int data = inputStream.read(); |
int read(byte[] b) | Liest Bytes aus dem Eingabestream und speichert sie im Byte-Arraybund gibt die tatsächliche Anzahl der gelesenen Bytes zurück. Gibt -1 zurück, wenn das Ende des Streams erreicht ist. | byte[] buffer = new byte[1024]; int bytesRead = inputStream.read(buffer); |
int read(byte[] b, int off, int len) | Liest bis zulenBytes aus dem Eingabestream und speichert sie im Byte-Arraybvonoffbeginnend an der Offset-Position, wobei die tatsächliche Anzahl der gelesenen Bytes zurückgegeben wird. Gibt -1 zurück, wenn das Ende des Streams erreicht ist. | byte[] buffer = new byte[1024]; int bytesRead = inputStream.read(buffer, 0, buffer.length); |
long skip(long n) | Überspringt und verwirftnBytes im Eingabestream und gibt die tatsächliche Anzahl der übersprungenen Bytes zurück. | long skippedBytes = inputStream.skip(100); |
int available() | Gibt die Anzahl der Bytes zurück, die gelesen werden können (ohne zu blockieren). | int availableBytes = inputStream.available(); |
void close() | Schließt den Eingabestream und gibt alle mit diesem Stream verbundenen Ressourcen frei. | inputStream.close(); |
void mark(int readlimit) | Setzt eine Markierung an der aktuellen Position im Stream,readlimitist die Obergrenze für die Anzahl der Bytes, die gelesen werden können. | inputStream.mark(1024); |
void reset() | Setzt den Stream an die Position der letzten Markierung zurück. Wenn keine Markierung vorhanden oder die Markierung ungültig ist, wird eine Ausnahme ausgelöstIOException。 | inputStream.reset(); |
boolean markSupported() | Prüft, ob der aktuelle Eingabestream unterstütztmark()undreset()Operation. | boolean isMarkSupported = inputStream.markSupported(); |
Zusätzlich zu InputStream gibt es einige andere Eingabestreams. Weitere Details finden Sie unter dem folgenden Link:
FileOutputStream
Diese Klasse wird verwendet, um eine Datei zu erstellen und Daten in die Datei zu schreiben.
Wenn die Zieldatei nicht existiert, bevor der Stream die Datei für die Ausgabe öffnet, erstellt der Stream die Datei.
Es gibt zwei Konstruktoren, die verwendet werden können, um ein FileOutputStream-Objekt zu erstellen.
Verwenden Sie einen Dateinamen vom Typ String, um ein Ausgabestrom-Objekt zu erstellen:
Sie können auch ein Dateiobjekt verwenden, um einen Ausgabestrom zu erstellen, um in eine Datei zu schreiben. Zuerst müssen wir die Methode File() verwenden, um ein Dateiobjekt zu erstellen:
Nachdem Sie das OutputStream-Objekt erstellt haben, können Sie die folgenden Methoden verwenden, um in den Stream zu schreiben oder andere Stream-Operationen auszuführen.
| Methode | Beschreibung | Beispielcode |
|---|---|---|
void write(int b) | Schreibt das angegebene Byte in den Ausgabestrom; die niedrigstwertigen 8 Bits vonbwird in den Stream geschrieben. | outputStream.write(255); |
void write(byte[] b) | Schreibt alle Bytes im Byte-Arraybin den Ausgabestream. | byte[] data = "Hello".getBytes(); outputStream.write(data); |
void write(byte[] b, int off, int len) | Schreibt Bytes aus dem Byte-Arraybbeginnend beim Offsetoffbeginnend beilenBytes in den Ausgabestream. | byte[] data = "Hello".getBytes(); outputStream.write(data, 0, data.length); |
void flush() | Leert den Ausgabestream und erzwingt, dass alle gepufferten Daten geschrieben werden, wodurch sichergestellt wird, dass die Daten sofort in die Zielausgabe geschrieben werden. | outputStream.flush(); |
void close() | Schließt den Ausgabestream und gibt alle mit diesem Stream verbundenen Ressourcen frei. Nach dem Schließen können keine Schreibvorgänge mehr ausgeführt werden. | outputStream.close(); |
Neben OutputStream gibt es noch einige andere Ausgabestreams. Weitere Details finden Sie unter dem folgenden Link:
Beispiel
Das folgende Beispiel demonstriert die Verwendung von InputStream und OutputStream:
fileStreamTest.java Datei-Code:
Das obige Programm erstellt zunächst die Datei test.txt, schreibt die angegebenen Zahlen in binärer Form in die Datei und gibt sie gleichzeitig auf der Konsole aus.
Da der obige Code binäres Schreiben verwendet, können verstümmelte Zeichen auftreten. Sie können das folgende Codebeispiel verwenden, um das Problem mit den verstümmelten Zeichen zu lösen:
Code der Datei fileStreamTest2.java:
Dateien und I/O
Es gibt auch einige Klassen im Zusammenhang mit Dateien und I/O, die wir kennen müssen:
Verzeichnisse in Java
Verzeichnisse erstellen:
Es gibt zwei Methoden in der File-Klasse, mit denen Ordner erstellt werden können:
- mkdir( )Die Methode erstellt einen Ordner. Sie gibt bei Erfolg true und bei Fehler false zurück. Ein Fehler bedeutet, dass der vom File-Objekt angegebene Pfad bereits existiert oder dass der Ordner nicht erstellt werden kann, weil der gesamte Pfad noch nicht existiert.
- mkdirs()Die Methode erstellt einen Ordner und alle seine übergeordneten Ordner.
Das folgende Beispiel erstellt den Ordner "/tmp/user/java/bin":
Code der Datei CreateDir.java:
Kompilieren und führen Sie den obigen Code aus, um das Verzeichnis "/tmp/user/java/bin" zu erstellen.
Hinweis:Java unterscheidet Dateipfadtrennzeichen unter UNIX und Windows automatisch je nach Konvention. Wenn Sie das Trennzeichen (/) in einer Windows-Version von Java verwenden, kann der Pfad trotzdem korrekt aufgelöst werden.
Verzeichnisse lesen
Ein Verzeichnis ist eigentlich ein File-Objekt, das andere Dateien und Ordner enthält.
Wenn Sie ein File-Objekt erstellen und es ein Verzeichnis ist, gibt der Aufruf der Methode isDirectory() true zurück.
Sie können die Liste der darin enthaltenen Dateien und Ordner extrahieren, indem Sie die Methode list() für dieses Objekt aufrufen.
Das folgende Beispiel zeigt, wie Sie die Methode list() verwenden, um den Inhalt eines Ordners zu überprüfen:
Code der Datei DirList.java:
Das Ergebnis des Kompilierens und Ausführens des obigen Beispiels ist wie folgt:
目录 /tmp bin 是一个目录 lib 是一个目录 demo 是一个目录 test.txt 是一个文件 README 是一个文件 index.html 是一个文件 include 是一个目录
Löschen von Verzeichnissen oder Dateien
Um eine Datei zu löschen, können Sie diejava.io.File.delete()Methode verwenden.
Der folgende Code löscht das Verzeichnis/tmp/java/. Beachten Sie, dass Sie beim Löschen eines Verzeichnisses sicherstellen müssen, dass sich keine anderen Dateien in diesem Verzeichnis befinden, damit es korrekt gelöscht werden kann; andernfalls schlägt das Löschen fehl.
Struktur des Testverzeichnisses:
/tmp/java/ |-- 1.log |-- test
