Streams - OverClockers.at

Werbung
Streams
Programmiermethodik
SS 08
Stefan Podlipnig
Universität Innsbruck
Übersicht
•
•
•
•
File-Klasse
Datenströme
Spezielle Themen
Serialisierung
Stefan Podlipnig
Programmiermethodik (SS 08)
2
FILE-KLASSE
Stefan Podlipnig
Programmiermethodik (SS 08)
3
Dateien
• In Java gibt es eine File-Klasse
– Liefert Informationen über Dateien und Verzeichnisse
– Diese Klasse wurde eingeführt, um Dateioperationen plattformunabhängig
durchzuführen
• Ein konkretes File-Objekt repräsentiert eine Datei oder ein
Verzeichnis im Dateisystem
• Der Verweis wird durch einen Pfadnamen spezifiziert
– Absoluter Pfadname (von der Wurzel ausgehend)
– Relativer Pfadname (abhängig vom aktuellen Verzeichnis)
– Pfadangaben sind plattformabhängig (siehe API)
Stefan Podlipnig
Programmiermethodik (SS 08)
4
File-Klasse
• Konstruktor stellt die Beziehung zu einer Datei im Verzeichnis her
• Beispiele für Konstruktoren
File(String parent, String child)
File(String pathname)
• Beispiele
String parent = "C:" + File.separator + "Test";
File f1 = new File("test1.txt");
File f2 = new File(parent,"test2.txt");
Stefan Podlipnig
Programmiermethodik (SS 08)
5
File-Klasse (einige Methoden)
• Allgemeine Methoden (Informationen über Dateien)
public
public
public
public
public
public
public
boolean canRead()
boolean canWrite()
boolean exists()
long lastModified()
String getAbsolutePath()
String getParent()
String [] list()
//Änderungszeit
//Absoluter Pfad
//Parent (Datei etc.)
//Verzeichnisinhalt
• Methoden für die Manipulation
public
public
public
public
public
boolean
boolean
boolean
boolean
boolean
renameTo(File dest)
setLastModified(long time);
delete()
createNewFile() throws IOException
mkdir()
• Siehe externes Beispiel StreamTest1.java
Stefan Podlipnig
Programmiermethodik (SS 08)
6
DATENSTRÖME
Stefan Podlipnig
Programmiermethodik (SS 08)
7
Motivation
• Die Java Bibliothek enthält eine ganze Reihe von Klassen, um
anspruchsvolle Ein- bzw. Ausgabeoperationen zu bewältigen und
von verschiedenen Datenquellen zu lesen und zu schreiben
• Das Ein- /Ausgabemodell in Java basiert auf sequentiellen
Datenströmen
– Beim Schreiben erzeugt man einen Ausgabestrom (in eine Datei oder einen
Speicher)
– Beim Lesen kommen die Daten von einem Eingabestrom (von einer Datei
oder einem Speicher)
Stefan Podlipnig
Programmiermethodik (SS 08)
8
IO-Begriffe
• Stream
– Die interne Repräsentation einer (externen) Datei oder einer Input/OutputEinheit in einem System
• Input
– Lesen der Daten von einer Datei oder einer Eingabeeinheit in einen Stream
– Stream wird als Input Stream bezeichnet
• Output
– Schreiben der Daten von einem Stream in eine Datei oder eine
Ausgabeeinheit
– Stream wird als Output Stream bezeichnet
• Source/Destination
– Jeder Stream hat eine Quelle (Source) und eine Senke (Destination)
Stefan Podlipnig
Programmiermethodik (SS 08)
9
Allgemeine Beispiele (1)
InputStream
JMenuBar mbar = new JMenuBar();
JMenu menu = new JMenu( "Datei" );
JMenuItem item = new JMenuItem( "Öffnen" );
item.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_MASK) );
item.addActionListener( this );
menu.add( item );
mbar.add( menu );
setJMenuBar( mbar );
InputStream
add( viewComponent );
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
setSize( 600, 400 );
}
public void actionPerformed( ActionEvent e )
{
JFileChooser d = new JFileChooser();
d.setFileFilter( new FileFilter()
}
public boolean accept(File f)
Tastatur
Programm
OutputStream
JMenuBar mbar = new JMenuBar();
JMenu menu = new JMenu( "Datei" );
JMenuItem item = new JMenuItem( "Öffnen" );
item.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_MASK) );
item.addActionListener( this );
menu.add( item );
mbar.add( menu );
setJMenuBar( mbar );
add( viewComponent );
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
setSize( 600, 400 );
}
OutputStream
public void actionPerformed( ActionEvent e )
{
JFileChooser d = new JFileChooser();
d.setFileFilter( new FileFilter()
}
public boolean accept(File f)
Bildschirm
Programm
Stefan Podlipnig
Programmiermethodik (SS 08)
10
Allgemeine Beispiele (2)
• Lesen/Schreiben einer Datei
------------------------------------
------------------------------------
InputStream
JMenuBar mbar = new JMenuBar();
JMenu menu = new JMenu( "Datei" );
JMenuItem item = new JMenuItem( "Öffnen" );
item.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_MASK) );
item.addActionListener( this );
menu.add( item );
mbar.add( menu );
setJMenuBar( mbar );
add( viewComponent );
------------------------------------
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
setSize( 600, 400 );
}
OutputStream
public void actionPerformed( ActionEvent e )
{
JFileChooser d = new JFileChooser();
d.setFileFilter( new FileFilter()
}
Programm
Stefan Podlipnig
Programmiermethodik (SS 08)
11
Strom (Modell)
• Ein Datenstrom wird durch eine Klasse repräsentiert
– Hat private Attribute (Name, Position etc.)
– Hat bestimmte Methoden
– Beispiele
• read() – Liest ein Element aus dem Strom
• write() – Schreibt ein Element in den Strom
• Vorteil
– Systemabhängigkeit wird in wenigen Klassen isoliert
– Rest des Programms systemneutral
Stefan Podlipnig
Programmiermethodik (SS 08)
12
Standard I/O
• Einfachster I/O - Mechanismus
– Texteingabe von der Tastatur
– Textausgabe auf den Bildschirm ("Konsole")
• Auf praktisch jedem System verfügbar
• Minimale Systemanforderungen
• Standard - I/O über vordefinierte Objekte
– System.in
– System.out
– System.err
Standard-Eingabe (← Tastatur)
Standard-Ausgabe (→ Bildschirm)
Fehlerausgabe (→ Bildschirm)
• in, out, error
– Statische, öffentliche Datenelemente der Klasse System
Stefan Podlipnig
Programmiermethodik (SS 08)
13
Klassenhierachien
• Es gibt 2 Hierarchien
– Byteströme
– Zeichenströme
• In jeder Hierarchie 2 Arten
– Datenströme
• Sind mit bestimmten Datenquellen oder Datensenken verbunden
• Lesen von Datenquellen bzw. schreiben in Datensenken
– Filterströme
•
•
•
•
Stefan Podlipnig
Sind nicht direkt mit einer Quelle oder Senke verknüpft
Sind mit einem Datenstrom verbunden
Agieren wie ein Filter vor diesem Datenstrom
Vorverarbeiten/Nachbearbeiten von Daten
Programmiermethodik (SS 08)
14
Byteströme
• Bytestrom ist eine Folge von Bytes
• Operationen
– Einzelne Bytes lesen/schreiben
– Ganze Bytefolgen lesen/schreiben
• Alle Byteströme werden abgeleitet von
– InputStream oder OutputStream
– Sind abstrakte Klassen
– Geben API vor und liefern eine partielle Implementierung
Stefan Podlipnig
Programmiermethodik (SS 08)
15
InputStream (Version 1.5)
• Zum Lesen von Bytes
• Datenströme (dunkel), Filterströme (hell)
Stefan Podlipnig
Programmiermethodik (SS 08)
16
OutputStream (Version 1.5)
• Zum Schreiben von Bytes
• Datenströme (dunkel), Filterströme (hell)
Stefan Podlipnig
Programmiermethodik (SS 08)
17
Zeichenströme
• Zeichenströme enthalten Texte in ASCII - oder Unicode
• Operationen
– Einzelne Zeichen lesen/schreiben
– Strings lesen/schreiben
– char-Arrays lesen/schreiben
• Zeichenströme werden abgeleitet von
– Reader oder Writer
– Sind abstrakte Klassen
Stefan Podlipnig
Programmiermethodik (SS 08)
18
Reader (Version 1.5)
• Zum Lesen von 16 bit Zeichen
• Datenströme (dunkel), Filterströme (hell)
Stefan Podlipnig
Programmiermethodik (SS 08)
19
Writer (Version 1.5)
• Zum Schreiben von 16 bit Zeichen
• Datenströme (dunkel), Filterströme (hell)
Stefan Podlipnig
Programmiermethodik (SS 08)
20
I/O – Superklassen (1)
• Reader und InputStream definieren ähnliche APIs für
unterschiedliche Datentypen, z.B.
– Reader
int read()
int read(char cbuf[])
int read(char cbuf[], int off, int len)
– InputStream
int read()
int read(byte cbuf[])
int read(byte cbuf[], int off, int len)
• Ähnliches gilt für Writer und OutputStream
Stefan Podlipnig
Programmiermethodik (SS 08)
21
I/O-Superklassen (2)
• Weitere Methoden für Eingabeströme
– Aktuelle Position im Strom markieren
– Zurücksetzen der aktuellen Position auf vorherige Markierung
– Input überspringen
• Weitere Methoden für Ausgabeströme
– Datenstrom leeren und damit noch gepufferte Daten verarbeiten (flush)
• Für alle Klassen gilt
– Automatisches Öffnen bei der Erzeugung
– Schließen durch den Aufruf der close-Methode
• Sobald ein Strom nicht mehr benötigt wird
• Gibt Ressourcen frei
Stefan Podlipnig
Programmiermethodik (SS 08)
22
Anwendung von Strömen
I/O - Typ
Speicher
(Memory)
Datenstrom
CharArrayReader, CharArrayWriter, ByteArrayInputStream,
ByteArrayOutputStream, StringReader, StringWriter, StringBufferInputStream
Pipe
PipedReader, PipedWriter, PipedInputStream, PipedOutputStream
File
FileReader, FileWriter, FileInputStream, FileOutputStream
Konkatenation (mehrerer
InputStreams)
Objekt - Serialisierung
Datenkonvertierung (Standardtypen in
rechnerunabhängiges Binärformat)
N/A, SequenceInputStream
N/A, ObjectInputStream, ObjectOutputStream
N/A , DataInputStream, DataOutputStream
Zählstreams (für Zeilennummern)
LineNumberReader, LineNumberInputStream
Vorausschauend (peeking ahead)
PushbackReader, PushbackInputStream
Ausgabe (Printing)
Pufferung
Filterströme (Filtering)
Konvertierung zwischen Byte- und
Datenströmen
Stefan Podlipnig
PrintWriter, PrintStream
BufferedReader, BufferedWriter, BufferedInputStream, BufferedOutputStream
FilterReader, FilterWriter, FilterInputStream, FilterOutputStream
InputStreamReader (byte in char), OutputStreamWriter (char in byte)
Programmiermethodik (SS 08)
23
Beispiel (FileStreams)
• Sehr einfach zu verwenden
• 4 Klassen
–
–
–
–
FileReader
FileWriter
FileInputStream
FileOutputStream
• Lesen aus / Schreiben in eine Datei im Dateisystem
• Konstruktor
– Mit String
– Mit File oder FileDescriptor
• Siehe externes Beispiel StreamTest2.java
Stefan Podlipnig
Programmiermethodik (SS 08)
24
Ströme (2 wichtige Konzepte)
• Zur I/O-Leistungssteigerung gibt es zwei wichtige Konzepte
– Datenpufferung
– Konkatenation
• Datenpufferung
– Zur Zwischenspeicherung
– Wenn I/O langsamer als die CPU ist
• Konkatenation
– Ströme können miteinander verbunden werden
– Der Output eines Stroms ist der Input eines anderen Stroms
• Ein Strom wird im Konstruktor eines anderen Stroms als Argument übergeben
• Verbinden von Filterströmen und Datenströmen
Stefan Podlipnig
Programmiermethodik (SS 08)
25
Datenpufferung
• Inputpuffer
– Speichert schon gelesene aber nicht verarbeitete Daten
• Nicht Zeichen für Zeichen lesen und an das Programm übergeben
• Folgen von Zeichen in Puffer kopieren und bei einer Leseoperation an das
Programm übergeben
• Outputpuffer
– Speichert temporäre Daten, die geschrieben werden
– Schreiben, wenn der Puffer voll wird (oder flush() aufgerufen wird)
• Viele I/O - Geräte unterstützen Operationen auf Blöcke
• Der Datentransfer zwischen Puffer und Objekten ist
normalerweise schnell (siehe Entwicklung von
Anwendungssystemen)
• Die Pufferung verbessert die Laufzeit von Programmen
Stefan Podlipnig
Programmiermethodik (SS 08)
26
Konkatenation (1)
• Beispieldeklaration
BufferedReader inStream = new BufferedReader(new FileReader("in.txt"));
– Verbindet einen BufferedReader mit einem FileReader
– Das Programm kann dann inStream.readLine() aufrufen, um die
Eingabedatei Zeile für Zeile zu lesen
• Datenfluss
– Textdatei → FileReader → BufferedReader → Speicher
Stefan Podlipnig
Programmiermethodik (SS 08)
27
Konkatenation (2)
• Für die Konkatenation muss ein Strom als Argument beim
Konstruktor eines anderen Stroms übergeben werden
• Beispiel (Java API)
public class BufferedReader extends Reader {
…
public BufferedReader(Reader in, int sz) {
super(in);
….
}
…
public BufferedReader(Reader in) {
this(in, defaultCharBufferSize);
}
…
}
• Benutzung
BufferedReader inStream = new BufferedReader(new FileReader("in.txt"));
Stefan Podlipnig
Programmiermethodik (SS 08)
28
Filterströme
• Es könne eigene Filterströme von den entsprechenden abstrakten
Klassen abgeleitet werden
• Ein Filterstrom verwendet weiteren Strom
– Zu lesende Daten werden aus dem darunter liegenden Strom gelesen,
gefiltert und an den Aufrufer weitergegeben
– Zu schreibende Daten werden gefiltert und in den darunter liegenden
Strom geschrieben
– Filtern kann viele Bedeutungen haben (Zeichen verändern, löschen oder
zählen, Zeilen zählen etc.)
• Eigenen Strom implementieren
–
Abstrakte Klasse verwenden
•
–
–
–
Input- und OutputStreams kommen oft gemeinsam vor, d.h. man wird meist
zwei Klassen implementieren müssen
Überschreiben der read- und write-Methoden (wenn benötigt)
Neue Methoden anbieten
Testen, ob die Implementierungen (Input, Output) korrekt
zusammenarbeiten
Stefan Podlipnig
Programmiermethodik (SS 08)
29
Beispiel
• BufferedReader
BufferedReader ist ein
Filterstrom (puffert)
…
BufferedReader d = new BufferedReader(new
InputStreamReader(System.in));
String input;
while (!(input = d.readLine()).equals("quit")) {
System.out.println(input);
}
…
• Beispiel für eigenen Filterstrom
– Siehe Implementierung von CheckedInputStream/CheckedOutputStream
im Paket java.util.zip
Stefan Podlipnig
Programmiermethodik (SS 08)
30
SPEZIELLE THEMEN
Stefan Podlipnig
Programmiermethodik (SS 08)
31
Scanning und Formatting
• Programme müssen mit dem Benutzer entsprechend interagieren
– Benutzereingaben
• Benutzer möchte Daten auf lesbare Art eingeben
• Programm zerlegt dann Eingabedaten für die Weiterverarbeitung
– Bildschirmausgabe
• Programm stellt lesbare Ausgabe zusammen
• Java I/O bietet dazu zwei APIs an
– Scanner-API zum Einlesen
– Formatting-API für die Ausgabe
Stefan Podlipnig
Programmiermethodik (SS 08)
32
Scanner
• Scanner wird für das Zerlegen des Inputs verwendet
– Input wird in Tokens zerlegt
– Tokens werden dann entsprechend weiterverarbeitet
– Seit Java 1.5 (früher StringTokenizer-Klasse für Strings)
• Methoden
– hasNext, hasNextInteger, hasNextDouble…
• Überprüfen ob noch ein Token (String), ein Integer-Wert, ein Double-Wert etc.
im Strom vorhanden ist
– next, nextInteger, nextDouble ….
• Auslesen des nächsten Tokens (String), Integer-Werts, Double-Werts etc.
Stefan Podlipnig
Programmiermethodik (SS 08)
33
Beispiel
import
import
import
import
java.io.File;
java.io.IOException;
java.util.Locale;
java.util.Scanner;
public final class StreamTest3 {
private StreamTest3() {
}
public static void main(final String[] args) throws IOException {
Scanner s = new Scanner(new File("usnumbers.txt"));
s.useLocale(Locale.US);
double sum = 0;
while (s.hasNext()) {
if (s.hasNextDouble()) {
sum += s.nextDouble();
} else {
s.next();
}
}
s.close();
System.out.println(sum);
}
}
Stefan Podlipnig
Programmiermethodik (SS 08)
34
Formatierung
• Klassen, die Formatierung berücksichtigen
– PrintWriter
– PrintStream
• System.out und System.err sind PrintStream-Instanzen
• Zwei Stufen der Formatierung werden unterstützt
– print und println formatieren individuelle Werte in der Standardform
– format formatiert jeden Wert an Hand eines Formatierungsstrings
– Für Formatstrings im printf-Stil
• Es gibt daher auch eine printf-Methode (äquivalent zu format)
– Etwas strikter als in C
• z.B. Exception, wenn Formatstring Fehler enthält
Stefan Podlipnig
Programmiermethodik (SS 08)
35
format-Methode (1)
• Formatiert Argumente mit einem Formatierungsstring
• Formatstring enthält Formatspezifizierer
– Formatierungsangaben folgen einem %-Zeichen und folgendem Syntax:
%[argument_index$][flags][width][.precision]conversion
– [argument_index] bezieht sich auf die Position in der Argumentenliste (erstes
Arg – 1$, zweites Arg - 2$ ..)
– [flags] ist eine Menge von Zeichen zur Modifikation der Ausgabe
– [width] ist die minimale Anzahl der Zeichen, die ausgegeben werden
– [precision] ist die maximale Anzahl der Zeichen oder Genauigkeit bei
Gleitkommazahlen
– conversion ist ein Zeichen, das die Formatierung des Arguments bestimmt erlaubte Formatierungen hängen vom jeweiligen Datentyp ab
• 1 oder 2 Buchstaben, die die entsprechende Konvertierung beschreiben
• Genaue Beschreibung siehe API
• Beispiele
%d, %f, %x, …
• Ist als einziger Teil nicht optional
Stefan Podlipnig
Programmiermethodik (SS 08)
36
format-Methode (2)
•
Unterschiedliche Kategorien der Konvertierung
–
–
General – allgemein anwendbar
Character – anwendbar auf alle Typen die Unicode-Zeichen
repräsentieren
•
–
char, Character, byte, Byte, short und Short
Numeric
•
Integral – anwendbar auf
–
•
Floating Point – anwendbar auf
–
–
float, Float, double, Double und BigDecimal
Date/Time – anwendbar auf
•
–
–
byte, Byte, short, Short, int, Integer, long, Long, BigInteger
long, Long, Calendar und Date
Percent – für '%' ('\u0025')
Line Separator – für plattformspezifisches“\n”
Stefan Podlipnig
Programmiermethodik (SS 08)
37
Beispiel
import java.io.IOException;
public final class StreamTest4 {
private StreamTest4() {
}
public static void main(final String[] args) throws IOException {
int i = 2;
double r = Math.sqrt(i);
System.out.format("The square root of %d is %f.%n", i, r);
System.out.format("%f, %1$+020.10f %n", Math.PI);
System.out.format("%4$s %3$s %2$s %1$s %4$s %3$s %2$s %1$s %n", "a",
"b", "c", "d");
System.out.format("%s %s %<s %<s %n", "a", "b", "c", "d");
System.out.format("%s %s %s %s %n", "a", "b", "c", "d");
System.out.format("%1$5s %s %s %s %n", "a", "b", "c", "d");
}
}
Stefan Podlipnig
Ausgabe:
The square root of 2 is 1,414214.
3,141593, +00000003,1415926536
d c b a d c b a
a b b b
a b c d
a a b c
Programmiermethodik (SS 08)
38
RandomAccessFile
• Bisher wurden Ströme besprochen, die nur einen sequentiellen
Zugriff gestatten
• Oft will man bei einer Datei nur einen bestimmten Teil lesen
• Java bietet eine Klasse RandomAccessFile an
– Wird für Lesen und Schreiben verwendet (unterschiedliche Argumente
beim Konstruktor)
new RandomAccessFile("in.txt", "r");
new RandomAccessFile("in.txt", "w");
new RandomAccessFile("in.txt", "rw");
– Wird von keiner Stream-Klasse abgeleitet
– Implementiert aber die zwei Interfaces DataOutput und DataInput
Stefan Podlipnig
Programmiermethodik (SS 08)
39
RandomAccessFile (File-Pointer)
• Die Klasse RandomAccessFile unterstützt das Konzept eines
File-Pointers
– File-Pointer zeigt auf die aktuelle Position in der Datei
– Bei der Erzeugung einer Datei zeigt er auf 0
– Aufrufe von read und write passen die Position abhängig von der Anzahl
der gelesenen/geschriebenen Bytes an
• Neben den Operationen read und write etc. gibt es Methoden
für die explizite Verwaltung des File-Pointers
– int skipBytes(int) — Überspringt die angegebene Anzahl von Bytes
(File-Pointer wird vorwärts bewegt)
– void seek(long) — Positioniert den File-Pointer vor der angegebenen
Position
– long getFilePointer() — Liefert die aktuelle Position des FilePointers
Stefan Podlipnig
Programmiermethodik (SS 08)
40
SERIALISIERUNG
Stefan Podlipnig
Programmiermethodik (SS 08)
41
Serialisierung von Objekten
• Der Zustand eines Objekts wird so abgespeichert, dass er wieder
rekonstruiert (ausgelesen) werden kann
– Serialisierung
• Objekt wird als Folge von Bytes in einen Strom geschrieben
– Deserialisierung
• Objekt wird als Folge von Bytes aus einem Strom gelesen
• Objekt existiert über die Ausführung eines Programms hinaus
• Objekt wird mit all seinen Komponenten in den Strom
geschrieben, d.h. Referenzen werden auch serialisiert
• Serialisierung – ObjectOutputStream
– Ein Objekt, das serialisiert werden soll, muss als Argument der
writeObject-Methode übergeben werden
• Deserialisierung – ObjectInputStream
– Mit der readObject-Methode kann ein Objekt eingelesen werden
• Dabei wird nur der Zustand des Objekts eingelesen
• Es werden keine Konstruktoren aufgerufen
Stefan Podlipnig
Programmiermethodik (SS 08)
42
Beispiel
import
import
import
import
import
java.io.FileInputStream;
java.io.FileOutputStream;
java.io.IOException;
java.io.ObjectInputStream;
java.io.ObjectOutputStream;
public final class StreamTest5 {
private StreamTest5() { }
public static void main(final String[] args) {
try {
FileOutputStream out = new FileOutputStream("MyObjects");
ObjectOutputStream s = new ObjectOutputStream(out);
s.writeObject("Today");
s.writeObject(1);
s.flush();
FileInputStream in = new FileInputStream("MyObjects");
ObjectInputStream sin = new ObjectInputStream(in);
String today = (String) sin.readObject();
Integer i = (Integer) sin.readObject();
System.out.println(today + " " + i);
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
}
}
Stefan Podlipnig
Programmiermethodik (SS 08)
43
Serialisierung (Voraussetzung)
• Ein Objekt kann nur serialisiert werden, wenn die entsprechende
Klasse das Interface Serializable implementiert
• Ist ein Marker-Interface (leeres Interface)
• Beispiel
– public class MySerClass implements Serializable { ... }
• Damit kann jede Instanz der Klasse serialisiert werden
• Bei der Serialisierung werden geschrieben
– Klasse
– Klassensignatur
– Werte der nicht statischen und nicht transienten Elemente (auch
Referenzen)
Stefan Podlipnig
Programmiermethodik (SS 08)
44
Anpassen der Serialisierung
• Serialisierung/Deserialisierung kann angepasst werden
• Implementieren der Methoden
– writeObject
• Für das Schreiben eines Objekts (Anpassen, zusätzliche Informationen etc.)
– readObject
• Für das Lesen eines Objekts (Lesen, Anpassen, Updates etc.)
• Form der writeObject-Methode
private void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();
// Benutzerspezifische Anpassung …..
}
• Form der readObject-Methode
private void readObject(ObjectInputStream s) throws IOException {
s.defaultReadObject();
// Benutzerspezifische Anpassung …..
// Zusätzliche Updates …
}
Stefan Podlipnig
Programmiermethodik (SS 08)
45
transient
• Oft soll ein Teil eines Objekts nicht serialisiert werden
• Schlüsselwort transient bei der Deklaration von Feldern
verwenden
– Das entsprechende Feld wird nicht serialisiert
– Beim Einlesen wird das entsprechende Feld mit einem Defaultwert
initialisiert
– Wenn das nicht gewünscht wird – überschreiben von readObject mit
einer entsprechenden Initialisierung
• Siehe externes Beispiel StreamTest6.java
Stefan Podlipnig
Programmiermethodik (SS 08)
46
Externalizable - Interface
• Will man die komplette Kontrolle über den Serialisierungsprozess,
dann muss die Klasse das Interface Externalizable
implementieren
• Externalizable erweitert Serializable
– 2 Methoden (writeExternal, readExternal)
• Eine Klasse muss
– das Interface implementieren
– Die Methoden writeExternal und readExternal implementieren und
miteinander koordinieren (und mit der Superklasse koordinieren)
• Die Methoden sind public und daher kann sie jedes Programm
benutzen, d.h. nur für nicht-sensitive Daten geeignet
Stefan Podlipnig
Programmiermethodik (SS 08)
47
Serialisierung unterbinden
• Beispiel
– Klasse B erbt von A
– A implementiert das Interface Serializable
– B sollte aber nicht serialisierbar sein
• Serialisierung unterbinden durch entsprechendes Überschreiben
(werfen einer Exception) der Methoden writeObject und
readObject
• Beispiel
private void writeObject(ObjectOutputStream s) throws
IOException,ClassNotFoundException {
throw new NotSerializableException();
}
Stefan Podlipnig
Programmiermethodik (SS 08)
48
Serialisierung und Vererbung
• Ist eine Basisklasse serialisierbar
– In einem Objekt einer abgeleiteten Klasse werden alle ererbten Attribute
der Basisklasse serialisiert
• Ist eine Basisklasse nicht serialisierbar
– Werden alle Attribute der Basisklasse serialisiert
– Dazu muss in der abgeleiteten Klasse der Zugriff auf einen DefaultKonstruktor der Basisklasse möglich sein
• Wird für die Initialisierung der Attribute benutzt
• Wenn dieser nicht vorhanden ist, wird eine Ausnahme geworfen
Stefan Podlipnig
Programmiermethodik (SS 08)
49
Versionsverwaltung (1)
• Verschiedene Versionen einer Klasse können Probleme bereiten
– Objekt wird serialisiert
– Klasse wird verändert
• Attribute löschen
• Typen ändern
– Deserialisieren funktioniert dann nicht mehr
• Erkennung in Java
– Bei der Serialisierung wird eine eindeutige Kennung geschrieben (UID)
• Hashcode aus Namen, Attributen, Parametern, Sichtbarkeit usw.
– Ändert sich eine Klasse, dann ändert sich der Hashcode
• Keine Kompatibilität mehr
Stefan Podlipnig
Programmiermethodik (SS 08)
50
Versionsverwaltung (2)
• SUID
– Benutzer kann die SUID (serialVersionUID) selbst berechnen
• Händisch
– Aufruf des Hilfsprogramms serialver mit Klassenname
– Ausgabe des Programms in das eigene Programm kopieren
• Eclipse unterstützt die Generierung
• Beispiel
static final long serialVersionUID = 9027745268614067035L;
– Man kann eine eigene SUID angeben (z.B. 1L)
– Bestimmte Änderungen (nicht alle) können vorgenommen werden wenn
die SUID gleich bleibt
• Neue Felder (werden beim Einlesen standardmäßig initialisiert)
• Fehlende Felder (werden ignoriert)
– Bei inkompatiblen Änderungen muss die SUID verändert werden
• Neu generieren oder eigene hochzählen
Stefan Podlipnig
Programmiermethodik (SS 08)
51
Herunterladen