Java Input/Output System (IO) Ziel: Schreiben und Lesen von Daten auf sequentielle Medien. Paket: java.io. ab Java 1.4 auch java.nio, hier nicht beru cksichtigt. Trennung in 2 Welten: - Byteorientierte IO (InputStreams, OutputStreams). Bytes sind 8bit-Werte ohne Interpretation des Inhaltes. - Zeichenorientierte IO (Readers, Writers). Zeichen sind 16-bitUnicode-Zeichen. Grundstruktur ist in beiden Fallen gleich. Sequentielle Datenstrome, die u ber Filter kombiniert werden konnen. Ein Filter ist ein sequentieller Datenstrom, der auf einem anderen sequentiellen Datenstrom aufbaut. Filter stellt immer einen Konstruktor zur Verfu gung, der den darunterliegenden Datenstrom als Parameter bekommt. Klasse File Klasse File reprasentiert einen Directory-Eintrag, der entweder ein einzelnes File oder ein Directory darstellt. Unterscheidung inkl. Existenztest mit Methoden boolean isFile(); boolean isDirectory(); Nur Directory-Information kann u ber File-Instanzen abgefragt werden. File erlaubt nicht das Lesen oder Schreiben des Inhalts. O ffnen von Files (Zugriff auf Inhalt) durch Konstruktoren fu r Datenstrome. Diese sind u berladen (File-Parameter, Pfadnamen, etc.). Bei Pfadnamen kann (unter Windows und Unix) '/' als DirectorySeparator verwendet werden (allgemein: File.separator). Klasse RandomAccessFile wird verwendet, wenn direkter Zugriff zu Dateiinhalt an einer bestimmten Position erforderlich ist. Bytestrome Abstrakte Klasse InputStream definiert Operationen zum sequentiellen Lesen von einzelnen Bytes und von Byte-Arrays. Konkrete Klasse FileInputStream liest Bytes von einem File. Konkrete Filterklasse BufferedInputStream erlaubt gepuffertes Lesen der Bytes => wesentlich schneller! InputStream in = new BufferedInputStream( new FileInputStream("inputFile")); int b = in.read(); while (b >= 0) { ... } in.close(); read() liefert unsigned Bytes (0..255) oder ß 1 zur Kennzeichnung von end-of-file. Daher int als Ergebnistyp verwendet. Abstrakte Klasse OutputStream definiert Methoden zum sequentiellen Schreiben von einzelnen Bytes und von Byte-Arrays. Konkrete Klasse FileOutputStream schreibt Bytes auf ein File. Konkrete Filterklasse BufferedOutputStream erlaubt gepuffertes Schreiben der Bytes => wesentlich schneller! OutputStream out = new BufferedOutputStream( new FileOutputStream("outputFile")); out.write((byte)42); ... out.flush(); out.write((byte)77); ... out.close(); Die flush()-Operation schreibt allfallige gepufferte Bytes auf das Ausgabemedium. Zeichenstro me Analog zu Bytestromen aber unter Verwendung der Namen Reader und Writer statt InputStream und OutputStream. Zum Beispiel schreibt ein FileWriter einen Zeichenstrom in eine Datei. Problem: Files sind byte-orientiert. Daher Abbildung von Zeichen auf Bytes erforderlich. FileReader/-Writer verwendet DefaultEncoding der Plattform. Zur expliziten Kontrolle des Encodings verwendet man InputStreamReader bzw. OutputStreamWriter. Beispiel: Writer out = new BufferedWriter( new OutputStreamWriter( new FileOutputStream("name"), "UTF8" //encoding parameter )); Serialisierung von Daten Programme arbeiten selten direkt auf Byte-Ebene sondern meistens mit den primitiven Java-Datentypen und/oder Klassen. Die Abbildung von Daten in Bytestrome heisst Serialisierung. Die Umkehrung hei t Deserialisierung. Datenstro me Zur Serialisierung primitiver Java-Datentypen (int, boolean, char, etc.), wird ein Datenstrom verwendet, das ist ein Strom, der die Schnittstelle DataInput bzw. DataOutput implementiert. Zur Implementierung von Datenstromen basierend auf Bytestromen existieren die konkreten Filter-Klassen DataOutputStream bzw. DataInputStream mit Lese-Schreiboperation fu r alle primitiven Java Datentypen (z.B. writeBoolean, writeDouble, writeUTF). Die Abbildung der Datentypen ist plattformunabhangig. Auf diese Weise geschriebene Files sind also portabel. Objektstro me Zur Serialisierung von Objekten wird ein Objektstrom verwendet. das ist ein Datenstrom, der zusatzlich die Schnittstelle ObjectInput bzw. ObjectOutput mit Methoden readObject bzw. writeObject implementiert. Zur Implementierung von Objektstromen basierend auf Bytestromen existieren die konkreten Filter-Klassen ObjectInputStream und ObjectOutputStream. Das Serialisieren von Objekten besteht aus dem Serialisieren der Typinformation (Klasse) plus (im Normalfall) dem Serialisieren aller Instanzvariablen, die nicht als transient markiert sind. Voraussetzung: Klasse muss Schnittstelle Serializable implementieren, sonst Exception. Referenzen auf andere Objekte (die Serializable sind) werden ebenfalls serialisiert, so dass ein ganzer Graph von Objekten (transitive Hu lle) geschrieben wird. Die Identitat von Objekten, die mehrfach referenziert werden, bleibt erhalten. Beim Deserialisieren bekommt man eine exakte Kopie der transitiven Hu lle eines serialisierten Objekts. Beieinflussung der Serialisierung von Objekten Durch Implementieren von optionalen Methoden. Details siehe javadoc von Serializable. 1. writeObject und/oder readObject Damit kann eine Klasse selbst das Serialisieren/Deserialisieren ihrer eigenen Instanzvariablen ausprogrammieren. Die Instanzvariablen der Basisklasse(n) sind davon nicht betroffen. Die Methoden mu ssen exakt diese Signatur aufweisen: private void writeObject(ObjectOutputStream out) throws IOException private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException; 2. writeReplace und/oder readResolve Damit kann ein Objekt beim Serialisieren/Deserialisieren durch ein anderes Objekt ersetzt werden. Anwendungsbeispiel: ein 'Remote'-Objekt konnte beim Schreiben durch eine Objekt-Referenz ersetzt werden. Beim Lesen konnte die Objekt-Referenz client-seitig durch ein Stub-Objekt ersetzt werden und server-seitig durch das Server-Objekt. Die Methoden konnen beliebige Sichtbarkeit aufweisen. ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException; ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException; Klassendiagramm Streams Object File FileDescriptor StreamTokenizer OutputStream DataOutput ObjectOutput InputStream RandomAccessFile DataInput ObjectOutputStream ObjectInputStream FilterOutputStream FilterInputStream PrintStream LineNumberInputStream BufferedOutputStream DataInputStream DataOutputStream BufferedInputStream ByteArrayOutputStream PushbackInputStream PipedOutputStream ByteArrayInputStream FileOutputStream PipedInputStream FileInputStream SequenceInputStream StringBufferInputStream ObjectInput Klassendiagramm Readers/Writers