Literatur

OutputStream

In diesem Kapitel beschäftigen wir uns mit den Klassen für  ausgehende Datenströme in Java. Schauen wir uns einmal eine Übersicht über die OutputStream-Klassen an.

Übersicht über OutputStreams

 

Hier kann man sehr gut erkennen, dass alle näher spezifizierten OutputStream-Klassen (z.B. FileOutputStream) von der abstrakten Superklasse OutputStream abgeleitet sind.


Nachfolgend ein Beispiel, wie man einzelne Werte in eine Datei schreibt:

 
// Import-Anweisung für unsere OutputStreams
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
// Import-Anweisung für die Klasse Date, 
// damit wir ein Datum in die Datei schreiben können  
import java.util.Date;
 
public class KomplexeAusgabe
{
    public static void main(String[] args)
    {
        // Deklaration eines FileOutputStreams mit einer Null-Initialisierung
        FileOutputStream fos = null;
        try
        {
            // Erstellung eines FileOutputStreams, damit wir in die 
            // Datei t.tmp schreiben können
            fos = new FileOutputStream("t.tmp");
 
            // Deklaration eines ObjectOutputStreams 
            // mit einer Null-Initialisierung
            ObjectOutputStream oos = null;
 
            try
            {
                // Neuer ObjectOutputStream, der die Schreibmethode enthält, 
                // wird erzeugt, indem der FileOutputStream dem Konstruktor 
                // übergeben wird
                oos = new ObjectOutputStream(fos);
 
                // Die Methode writeInt schreibt einen einfachen 
                // int-Datentypen in die Datei
                oos.writeInt(12345);
 
                // Die Methode writeObject schreibt komplexe 
                // Datentypen in die Datei
                oos.writeObject("Today");
                oos.writeObject(new Date());
            }
            // Fehlerbehandlung, falls ein Fehler beim 
            // eigentlichen Schreiben auftritt
            catch (IOException ex)
            {
                // Ausgabe der Aufruferliste im Fehlerfalle
                ex.printStackTrace();
            }
            // Schließe auf jeden Fall den ObjectOutputStream
            finally
            {
                try
                {
                         // Überprüfung, ob oos überhaupt initialisiert wurde
                         if(oos!=null)
                         {
                               oos.close();
                          }
                }
                catch (IOException ex)
                {
                    // Ausgabe der Aufruferliste im Fehlerfalle
                    // Könnte man beim Close ignorieren, da der 
                    // ObjectOutputStream in der Regel dann nicht mehr 
                    // vorhanden ist                    
                    ex.printStackTrace();
                }
            }
        }
        // Auffangen der FileNotFoundException, falls die Datei,
        // die beschrieben werden soll, nicht gefunden werden konnte        
        catch (FileNotFoundException ex)
        {
             // Ausgabe der Aufruferliste im Fehlerfalle
            ex.printStackTrace();
        }
        // Schließe auf jedenfall den FileOutputStream
        finally
        {
            try
            {
                // Überprüfung,ob fos überhaupt initialisiert wurde
                if(fos!=null)
                {
                      fos.close();
                 }
            }
            catch (IOException ex)
            {
                // Ausgabe der Aufruferliste im Fehlerfalle
                // Könnte man beim Close ignorieren, da der ObjectOutputStream
                // in der Regel dann nicht mehr vorhanden ist
                ex.printStackTrace();
            }
        }
    }
}

In dem obigen Beispiel erstellen wir uns zunächst einen FileOutputStream. Der Konstruktor für die Objekterzeugung verlangt einen Dateinamen, dies kann auch ein ganzer Pfad zu einer Datei sein. Der Konstruktor von FileOutputStream kann eine FileNotFoundException werfen, falls er die übergebene Datei nicht findet. Anschließend erzeugen wir den eigentlichen OutputStream, über den wir in die Datei schreiben mit Hilfe des zuvor erstellten FileOutputStream-Objektes fos.

Sowohl der Konstruktor der Klasse ObjectOutputStream als auch dessen write-Methoden können eine sogenannte IOException werfen. Die IOException kann z.B. auftreten, wenn die Datei schreibgeschützt ist. Da jede einzelne write-Methode diese IOException werfen kann, haben wir Sie hier in einem try-Block zusammengefasst. Man kann natürlich für jede write-Methode einen eigenen try-catch-Block aufbauen, jedoch macht dies meistens keinen Sinn, da bei einem Fehlschlag der ersten write-Methode in der Regel auch alle folgenden write-Methoden fehlschlagen werden.

Nachdem wir das Schreiben beendet haben, müssen wir dafür sorgen, dass alle Streams auch geschlossen werden, damit diese nicht den Zugriff auf die Datei blockieren. In allen catch-Blöcken lassen wir uns lediglich die Aufruferliste ausgeben. Für einen Anwender sollte man allerdings eine verständlichere Fehlermeldung ausgeben wie z.B. "Die Datei t.tmp wurde nicht gefunden!" oder "Es konnte nicht in die Datei t.tmp geschrieben werden!" (abhängig davon, wo der Fehler aufgetreten ist).

Über die Methode writeObject könnte man nun auch unsere Klasse Punkt aus dem vorhergegangenen Kapitel speichern. Schauen wir uns dies in einem weiteren Beispiel an:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Vector;
 
public class PunktSchreiben
{
 
    public static void main(String[] args)
    {
        FileOutputStream fos = null;
        try
        {
            Punkt p2 = new Punkt();
            p2.setX(33);
            Punkt p = new Punkt();
            p.setX(22);
            Vector vec = new Vector();
            vec.add(p);
            vec.add(p2);

            // Erstellung eines FileOutputStreams, damit wir in die Datei 
            // punkt.tmp schreiben können       
            fos = new FileOutputStream("punkt.tmp");

            ObjectOutputStream oos = null;

            try
            {
                // ObjectOutputStreams, der die eigentliche 
                // Schreibmethode enthält, wird mit dem 
                // FileOutputStream erzeugt.
                oos = new ObjectOutputStream(fos);

                // Schreiben des Vektors in eine Datei mit den Objekten 
                // der Klasse Punkt
                oos.writeObject(vec);
 
            }
             // Fehlerbehandlung, falls ein Fehler beim eigentlichen 
            // Schreiben auftritt
            catch (IOException ex)
            {
                // Ausgabe der Aufruferliste im Fehlerfalle
                ex.printStackTrace();
            }
            // Schließe auf jeden Fall den ObjectOutputStream
            finally
            {
                try
                {
                    // Überprüfung, ob oos überhaupt initialisiert wurde
                    if(oos!=null)
                    {
                        oos.close();
                    }
                }
                catch (IOException ex)
                {
                    // Ausgabe der Aufruferliste im Fehlerfalle
                    // Könnte man beim Close ignorieren, da der 
                    // ObjectOutputStream in der Regel dann nicht mehr 
                    // vorhanden ist.
                    ex.printStackTrace();
                }
            }
 
        }
        // Auffangen der FileNotFoundException, falls die 
        // Datei, die beschrieben werden soll,
        // nicht gefunden werden konnte
        catch (FileNotFoundException ex)
        {
            // Ausgabe der Aufruferliste im Fehlerfalle
            ex.printStackTrace();
        }
        // Schließe auf jeden Fall den FileOutputStream
        finally
        {
            try
            {
                // Überprüfung, ob fos überhaupt initialisiert wurde
                if(fos!=null)
                {
                    fos.close();
                }
            }
            catch (IOException ex)
            {
                // Ausgabe der Aufruferliste im Fehlerfalle
                // Könnte man beim Close ignorieren, da der 
                // ObjectOutputStream in der Regel dann nicht 
                // mehr vorhanden ist                
                ex.printStackTrace();
            }
        }
    }
}

Das obige Beispiel ähnelt sehr unserem ersten. Wir erzeugen hier zwei Objekte unserer Klasse Punkt und legen diese in einem Objekt der Klasse Vector ab (Anmerkung: Ein Vector ist gewissermaßen ein dynamisches Array, welches in der Größe zur Laufzeit variieren kann).  Anschließend schreiben wir dieses Objekt, welches unsere zwei Punkt-Objekte enthält, in die Datei punkt.tmp, da wir in dem folgenden Kapitel unsere hier geschriebenen Objekte wieder einlesen möchten. Der Aufwand für die Fehlerbehandlung ist in diesem Falle größer als das eigentliche Schreiben in die Datei.

Die Verwendung anderer Streams ist ähnlich und unterscheidet sich nur geringfügig. In dem nun folgenden Kapiteln behandeln wir das Einlesen unserer geschriebenen Datei.