FHZ Hochschule für Technik+Architektur Luzern Abteilung Informatik, Fach Programmieren K30 DATENSTRÖME (STREAMS) K30 DATENSTRÖME (STREAMS) 1 Einleitung Das grundlegende Konzept für die Ein- und Ausgabe von Daten bilden bei Java die sogenannten Datenströme oder Streams. Ein Programm liest eine Folge von Bytes aus einem Eingabestrom (Input Stream) und schreibt Bytes in einen Ausgabestrom (Output Stream). Der Hauptvorteil von Datenströmen ist die vollständige Abstraktion von der Art des dahinterliegenden I/O-Gerätes. Das Package java.io stellt neben diversen Klassen für Datenströme auch unterstützende Klassen sowie spezifische IOException-Klassen bereit. Java unterscheidet zwei Arten von Datenströmen: § Byte-Datenströme § Zeichen-Datenströme Folgende Teilwörter in den Klassennamen weisen auf die erste oder zweite Art von Datenstrom hin: § InputStream, OutputStream § Reader, Writer Datenströme sind speziell von Bedeutung für folgende I/O: § Dateien (Files) § Tastatur/Konsole § Serialisierung von Objekten (Persistenz) K30_Datenstroeme-L, V8 © H. Diethelm Seite 1/9 Abteilung Informatik, Fach Programmieren FHZ Hochschule für Technik+Architektur Luzern K30 DATENSTRÖME (STREAMS) 2 Byte-Datenströme (8Bit-Streams) Folgende Illustration (keine bestimmte Notation) zeigt, wie in der Regel für I/O Stream-Objekte "hintereinander geschaltet" werden: z.B.: - Datei auf Festplatte - Modem - Netzwerk - Scanner - Tastatur - RS232 Quelle Bytes aFileInputStream Byte-Datenstrom 0...255 InputStream-Objekte aDataInputStream readDouble() Programm writeInt(123) aDataOutputStream Byte-Datenstrom 0...255 OutputStream-Objekte aFileOutputStream Senke Bytes K30_Datenstroeme-L, V8 © H. Diethelm z.B.: - Datei auf Festplatte - Modem - Netzwerk - Drucker - Konsole - RS232 Seite 2/9 FHZ Hochschule für Technik+Architektur Luzern Abteilung Informatik, Fach Programmieren K30 DATENSTRÖME (STREAMS) Folgendes Klassendiagramm zeigt wichtige Klassen für ByteDatenströme (nur Ausschnitt): Object InputStream OutputStream read():int close() write() flush() close() FileInputStream FilterInputStream read():int FileOutputStream FilterOutputStream write() DataInputStream PrintStream DataOutputStream readDouble() readByte() checkError() print() println() writeBoolean() writeLong() <<interface>> DataOutput writeBoolean() writeLong() <<interface>> DataInput readDouble() readByte() Bemerkungen: § DataInputStream und DataOutputStream unterstützen den I/O mit elementaren Datentypen. Die Interfaces definieren die entsprechenden Methoden. § FileInputStream und FileOutputStream unterstützen den I/O mit Files. K30_Datenstroeme-L, V8 © H. Diethelm Seite 3/9 Abteilung Informatik, Fach Programmieren FHZ Hochschule für Technik+Architektur Luzern K30 DATENSTRÖME (STREAMS) § PrintStream ermöglicht die Ausgabe von ASCII-Text. § int-Werte im Zusammenhang mit read() und write() dürfen nur Werte im Bereich 0...255 (vgl. 1 Byte) annehmen! Im Falle von EOS (End Of Stream) oder speziell EOF (End Of File) liefert read() den Wert -1 zurück. Folgendes Codestück illustriert, wie Stream-Objekte für einen Input "hintereinander geschaltet" werden, indem der Vorgänger als aktueller Parameter dem Konstruktor des Nachfolgers übergeben wird: FileInputStream aFileInputStream = new FileInputStream("data.bin"); DataInputStream aDataInputStream = new DataInputStream(aFileInputStream); double d = aDataInputStream.readDouble(); Also: data.bin ð aFileInputStream ð aDataInputStream ð d Anwendungsbeispiele: § Mit Hilfe von Byte-Datenströmen können einfach binäre Dateien gehandhabt werden. Binäre Dateien kann man logisch als eine beliebig lange Sequenz von Bytes betrachten. § Die angesprochene Objekt-Serialisierung basiert ebenfalls auf Byte-Datenströmen. § Die vorinstanzierten Objekte System.in (InputStream) und System.out (PrintStream) für den Standard-I/O bedienen sich auch Byte-Datenströmen. K30_Datenstroeme-L, V8 © H. Diethelm Seite 4/9 Abteilung Informatik, Fach Programmieren FHZ Hochschule für Technik+Architektur Luzern K30 DATENSTRÖME (STREAMS) 3 Zeichen-Datenströme (16Bit-Streams) Intern stellt Java Zeichen mit dem 16Bit-Unicode dar. Um der Internationalisierung gerecht zu werden, arbeiten deshalb die Reader- und Writer-Klassen mit Zeichen anstelle von Bytes: z.B.: - Datei auf Festplatte - Modem - Netzwerk - Scanner Quelle Zeichen aBufferedReader Zeichen-Datenstrom 0...65535 Reader-Objekte aStreamTokenizer nextToken() Programm newLine() aBufferedWriter Zeichen-Datenstrom 0...65535 Writer-Objekte aPrintWriter Senke Zeichen K30_Datenstroeme-L, V8 © H. Diethelm z.B.: - Datei auf Festplatte - Modem - Netzwerk - Drucker Seite 5/9 FHZ Hochschule für Technik+Architektur Luzern Abteilung Informatik, Fach Programmieren K30 DATENSTRÖME (STREAMS) Folgendes Klassendiagramm zeigt wichtige Klassen für ZeichenDatenströme (nur Ausschnitt): Object Reader Writer StreamTokenizer close() flush() write() nextToken() read():int close() BufferedReader InputStreamReader BufferedWriter PrintWriter OutputStreamWriter close() readLine():String read():int close() flush() write() checkError() print() println() close() flush() write() FileReader FileWriter Bemerkungen: § Reader und Writer unterstützen den I/O mit Zeichen. § BufferedReader und BufferedWriter erhöhen die Performance. § InputStreamReader und OutputStreamWriter sind Adapter und ermöglichen die Koppelung von 8Bit- und 16BitStreams. § FileReader und FileWriter unterstützen den I/O mit Files. § PrintWriter ermöglicht die Ausgabe von Zeichen. § Im Falle von EOS (End Of Stream) oder speziell EOF (End Of File) liefert read() den Wert -1 zurück. K30_Datenstroeme-L, V8 © H. Diethelm Seite 6/9 Abteilung Informatik, Fach Programmieren FHZ Hochschule für Technik+Architektur Luzern K30 DATENSTRÖME (STREAMS) Folgendes Codestück illustriert, wie Stream-Objekte für einen Output "hintereinander geschaltet" werden: PrintWriter aPrintWriter = new PrintWriter(aDest); BufferedWriter aBufferedWriter = new BufferedWriter(aPrintWriter); aBufferedWriter.newLine(); Also: newLine()ðaBufferedWriterðaPrintWriterðaDest Anwendungsbeispiel: § Mit Hilfe von Zeichen-Datenströmen können einfach Textfiles gehandhabt werden. Textfiles kann man logisch als eine beliebig lange Kette von Zeichen auffassen. 4 Standard-Datenströme Die Klasse System aus dem Package java.lang stellt ohne explizites new folgende Byte-Datenströme bereit: § System.in ð Eingabe via Tastatur § System.out ð Ausgabe via Konsole § System.err ð spezieller Ausgabekanal für Fehlermeldungen via Konsole (vgl. System.out kann umgeleitet sein.) K30_Datenstroeme-L, V8 © H. Diethelm Seite 7/9 FHZ Hochschule für Technik+Architektur Luzern Abteilung Informatik, Fach Programmieren K30 DATENSTRÖME (STREAMS) Programmbeispiel: import java.io.*; public class ConsoleIO { public static void main(String[] args) { String fileName = prompt("Type a File Name: "); System.out.println(fileName); } private static String prompt(String message) { String reply = ""; try { System.out.print(message); // System.out & System.in operates on Bytes. System.out.flush(); // Forces any buffered output to be written. InputStreamReader aInputStreamReader = new InputStreamReader(System.in); // InputStreamReader operates on Characters. BufferedReader aBufferedReader = new BufferedReader(aInputStreamReader, 1); // BufferedReader allows reading a whole Line. reply = aBufferedReader.readLine(); // can throw IOException } catch (IOException e) { System.out.println("Keyboard-Input: " + e.getMessage()); System.exit(1); // Causes the JVM to exit with Error-Code 1. } return reply; } } K30_Datenstroeme-L, V8 © H. Diethelm Seite 8/9 FHZ Hochschule für Technik+Architektur Luzern Abteilung Informatik, Fach Programmieren K30 DATENSTRÖME (STREAMS) Folgende Tabellen helfen bei der Klassenauswahl: Input Daten liegen wie folgt vor: ð folgende Klasse/Unterklasse: Zeichen im ASCII oder Unicode FileReader, falls Quelle Datei InputStreamReader, falls Quelle 8Bit-Stream binäre Daten DataInputStream persistente Objekte ObjectInputStream Output Daten liegen wie folgt vor: ð folgende Klasse/Unterklasse: Zeichen im ASCII oder Unicode FileWriter, falls Senke Datei OutputStreamWriter, falls Senke 8Bit-Stream binäre Daten DataOutputStream persistente Objekte ObjectOutputStream K30_Datenstroeme-L, V8 © H. Diethelm Seite 9/9