Literatur

InputStream

In diesem Kapitel beschäftigen wir uns mit dem Einlesen von Daten. Für das Einlesen eigehender Datenströme steht in Java die Basisklasse InputStream zur Verfügung. Daten können sowohl von einer Client-Server-Anwendung als auch aus Dateien eingelesen werden. In diesem Teil beschränken wir uns auf das Einlesen von Dateien. Das nun folgende Bild zeigt eine Übersicht über die InputStream-Klassen (Anzahl kann je nach Java-Version abweichen).

Übersicht über InputStreams

Wir haben in dem vorigen Kapitel die Datei t.tmp geschrieben. Nun lesen wir die Datei t.tmp aus:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Date;

public class KomplexesEinlesen
{
    public static void main(String[] args)
    {
        FileInputStream fis = null;
        try
        {
            // Erstellung eines FileInputStreams, damit wir 
            // aus der Datei t.tmp lesen können
            fis = new FileInputStream("t.tmp");

            ObjectInputStream ois = null;
            try
            {
                // Erstellung eines ObjectInputStreams, der 
                // die eigentlichen Lesemethoden enthält
                // wird mit dem FileInputStream erzeugt.
                ois = new ObjectInputStream(fis);

                // Die Methode readInt liest einen 
                // einfachen int-Datentypen aus der Datei
                int i  = ois.readInt();

                // Die Methode readObject liest komplexe 
                // Datentypen aus der Datei
                String today  = (String)ois.readObject();
                Date date = (Date) ois.readObject();
                System.out.println(date.toString());
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
            }
            catch(ClassNotFoundException ex)
            {
                ex.printStackTrace();
            }
            finally
            {
                try
                {
                         if(ois!=null)
                         {
                            ois.close();
                         }
                }
                catch (IOException ex)
                {
                    ex.printStackTrace();
                }
            }
        }
        // Auffangen der FileNotFoundException, falls 
        // die Datei, die gelesen werden soll,
        // nicht gefunden werden konnte
        catch (FileNotFoundException ex)
        {
            ex.printStackTrace();
        }
        finally
        {
            try
            {
                if(fis!=null)
                {
                    fis.close();
                }
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
            }
        }
    }
}

In dem obigen Beispiel erstellen wir uns zunächst ein Objekt der Klasse FileInputStream. Der Konstruktor für die Objekterzeugung verlangt einen Dateinamen, dies kann auch ein ganzer Pfad zu einer Datei sein. Der Konstruktor von FileInputStream kann eine FileNotFoundException werfen, falls er die übergebene Datei nicht findet. Anschließend erzeugen wir das eigentliche InputStream-Objekt, über das wir aus der Datei lesen, mit Hilfe des zuvor erstellten FileInputStream-Objektes fis.

Sowohl der Konstruktor der Klasse ObjectInputStream als auch dessen read-Methoden können eine sogenannte IOException werfen. Die IOException kann z.B. auftreten, wenn die Datei lesegeschützt ist. Da jede einzelne read-Methode diese IOException werfen kann, haben wir Sie hier in einem try-Block zusammengefasst. Man kann natürlich für jede read-Methode einen eigenen try-catch-Block aufbauen. Dies macht jedoch macht meistens keinen Sinn: Denn, wenn die erste read-Methode fehlschlägt, werden in der Regel auch alle folgenden read-Methoden fehlschlagen. Nachdem wir das Lesen beendet haben, müssen wir auf jeden Fall dafür sorgen, dass alle Streams auch geschlossen werden, damit diese nicht den Zugriff auf die Datei blockieren. In den gesamten catch-Blöcken lassen wir uns lediglich die Aufruferliste ausgeben. Für einen Anwender sollte man allerdings einen geeigneteren Fehler ausgeben, wie z.B. "Die Datei t.tmp wurde nicht gefunden!" oder "Es konnte nicht aus der Datei t.tmp gelesen werden!" (abhängig davon, an welcher Stelle der Fehler aufgetreten ist).

Über die Methode readObject könnte man auch nun unsere Klasse Punkt aus dem vorhergegangenen Oberkapitel lesen. Schauen wir uns dieses in einem weiteren Beispiel an.

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Vector;

public class PunktLesen
{
    public static void main(String[] args)
    {
        FileInputStream fis = null;
        try
        {
            // Erstellung eines FileInputStreams, damit 
            // wir aus der Datei punkt.tmp lesen können
            fis = new FileInputStream("punkt.tmp");
            ObjectInputStream ois = null;
            try
            {
                // Erstellung eines ObjectInputStreams, der 
                // die eigentlichen Lesemethoden enthält,                
                // wird mit dem FileInputStream erzeugt
                ois = new ObjectInputStream(fis);

                // Lesen des Vektors (mit den Punkt-Objekten) aus der Datei
                Vector vec = (Vector) ois.readObject();

                // Ausgabe der x-Werte unserer Punkt-Objekten
                for(int i =0; i < vec.size(); i++)
                {
                    System.out.println("X-Wert von Punkt "+i+ " ist: " 
                        +((Punkt)vec.elementAt(i)).getX());
                }
 
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
            }
            catch (ClassNotFoundException ex)
            {
                ex.printStackTrace();
            }
            finally
            {
                try
                {
                    if(ois!=null)
                    {
                        ois.close();
                    }
                }
                catch (IOException ex)
                {
                    ex.printStackTrace();
                }
            }
 
        }
        catch (FileNotFoundException ex)
        {
            ex.printStackTrace();
        }
        finally
        {
            try
            {
                if(fis!=null)
                {
                    fis.close();
                }
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
            }
        }
    }
}

Das obige Beispiel ähnelt sehr unserem ersten. Wir lesen hier unseren zuvor geschriebenen Vektor mit unseren zwei Punkt-Objekten aus. Da die eingelesenen Objekte zunächst der Klasse Object angehören, müssen wir eine Konvertierung durchführen. Anschließend geben wir hier die x-Werte unserer gelesenen Punkt-Objekte aus.