Zurück   Weiter

14 Daten lesen und schreiben mit Streams

Das Lesen von und Schreiben in Datenquellen wird in Java mit Streams realisiert. Eine Datenquelle kann hierbei eine Datei, eine Textkonsole ,eine Netzwerkverbindung aber auch z.B. ein String sein. Das Lesen und Schreiben wird in jedem Fall gleich behandelt. Einen Stream kann man sich als ein senkrechtes Rohr vorstellen, in das von oben die Daten eingefüllt werden. Am unteren Ende befindet sich ein Ventil, welches geöffnet werden kann, um die Daten wieder auszulesen. Die Streams können in zwei Kategorien einteilt werden. Zum einen gibt es die Streams, die eine direkte Verbindung zu den Datenquellen herstellen z.B. FileInputStream. Die zweite Gruppe besteht aus Klassen, die ein formatiertes Lesen aus und Schreiben aus Streams ermöglichen. Alle Stream-Klassen findet man im Package java.io

14.1 Die Klasse InputStream

Die Klasse java.io.InputStream ist die Superklasse aller Streams zum Lesen von Daten. Sie enthält nur die Methoden, welche unbedingt nötig sind, um ein Schreiben in einen Stream zu ermöglichen. InputStream ist eine abstrakte Klasse, das heisst es können keine direkten Instanzen dieser Klasse erzeugt werden.

14.1.1 Die Methode read()

Jede von InputStream abgeleitete Klasse muss die Methode public int read() implementieren. Diese Methode beschreibt das eigentliche Lesen aus dem Stream. Die Implementierung von read ist abhängig von der gewählten Datenquelle. Der Aufruf von read() liest genau ein byte aus dem Stream und gibt dieses als int zurück.

14.1.2 Die Methode read(byte[])

Mit public int read(byte[] bytes) ist es möglich mehrere bytes gleichzeitig aus einem Stream auszulesen. Das byte[] muss dazu vorher initialisiert worden sein. Die maximale Anzahl der gelesenenen bytes ist gleich der Länge des Arrays. Die tatsächliche Anzahl der gelesenen Zeichen wird als int-Wert zurückgegeben. Wenn alle Zeichen aus dem Stream ausgelesen wurden, so erhält man den Wert -1 zurück.

14.1.3 Die Methode read(byte[], int, int)

Die Methode public int read(byte[] bytes, int offset, int length) versucht aus einem Stream eine length Zeichen auszulesen und fügt diese an der Stelle offset in das byte[] bytes ein. Die Methode gibt die Anzahl der tatsächlich ausgelesenen bytes als int-Wert zurück.

14.1.4 Die Methode close()

Jede Verbindung zu einem InputStream die aufgebaut wurde, sollte auf jeden Fall wieder geschlossen werden. Offene Verbindungen vor allem zu Dateien oder Servern können Datenverluste verursachen. Besonders wenn es irgendwelche unvorhergesehene Störungen im Programm oder Betriebssystem gibt. Am sichersten ist es die Zugriffe auf einen InputStream immer mit dem Aufruf von close() in einem finally-Block abzuschliessen.

  ...
  InputStream in = null;
  try {
    ...
    ...
  } catch(...Exception ex) {
  } finally {
    try {
      in.close();
    } catch(Exception ex) {}
  }
  ...

14.2 Die Klasse OutputStream

java.io.OutputStream ist die Superklasse aller Streamklassen zum Schreiben von Daten. Sie enthält die Methoden die unbedingt nötig sind, um in einen Stream zu schreiben. Jedes gewüschte formattierte Schreiben muss in davon abgeleiteten Klassen implementiert werden. Die Klasse OutputStream selbst ist abstrakt, dass heisst von ihr können keine Instanzen erzeugt werden.

14.2.1 Die Methode write(int)

Diese Methode schreibt genau ein byte in einen Stream. Dabei werden nur die ersten 8 Bit des Integers in den Stream geschrieben. Die restlichen 24 Bit werden ignoriert. Diese Methode ist abstrakt und muss von der abgeleiteten Klasse entsprechend implementiert werden.

14.2.2 Die Methode write(byte[])

public void write(byte[] bytes) schreibt alle bytes des Arrays in den Stream. Der Aufruf dieser Methode hat den gleichen Effekt wie der Aufruf der folgenden Methode mit den Parametern bytes, 0, bytes.length.

14.2.3 Die Methode write(byte[], int, int)

Die Methode public void write(byte[] bytes, int offset, int length) schreibt length Zeichen des byte-Arrays bytes in einen Stream. Das erste geschriebene Zeichen ist das Zeichen an der Stelle offset.

14.2.4 Die Methode flush()

public void flush() sorgt bei gepufferten Streams dafür, dass alle momentan im Puffer befindlichen Daten in den Stream geschrieben werden. Diese Method sollte von allen Streams überschrieben werden, welche von OutputStream abgeleitet sind und einen Datenpuffer verwenden. In der Klasse OutputStream selbst besitzt die Methode flush keine Funktionalität.

14.2.5 Die Methode close()

Beim OutputStream gilt das gleiche wie beim InputStream. Ach hier sollte jede Verbindung die aufgebaut wurde, auf jeden Fall wieder geschlossen werden. Der Aufruf von close() erfolgt auch hier am Besten in einem finally-Block.

  ...
  OutputStream out = null;
  try {
    ...
    ...
  } catch(...Exception ex) {
  } finally {
    try {
      out.close();
    } catch(Exception ex) {}
  }
  ...

14.3 Datenquellen-Streams

Die Datenquellen Streams verknüpfen einen Stream direkt mit einer Datenquelle. Datenquelle kann eine Datei, eine Netzwerkverbindung oder auch ein byte-Array sein. In der Regel sind sie direkte Nachfahren der InputStream- oder OutputStream-Klasse. Meistens besitzen sie auch nur sehr einfache, unkomfortable Möglichkeiten die Daten auszulesen. Sie werden nur dazu verwendet eine Verbindung zu den Datenquellen herzustellen oder sie dienen als Superklasse um eigene Streams zu implementieren, die ein spezielles Lesen und Schreiben von Daten ermöglichen.

class FileCopier {
  private static byte[] buffer = new byte[10000];

  public void copyFile(File from, File to) throws IOException {
    FileInputStream in = null;
    FileOutputStream out = null;
    in = new FileInputStream(from);
    out = new FileOutputStream(to);
    try {
      while (true) {
        int amountRead = from.read(buffer);
        if(amountRead == -1) {
          break;
        }
        to.write(buffer, 0, amountRead);
      }
    } finally {
      try {
        from.close();
      } catch(Exception ex) {}
      try {
        to.close();
      } catch(Exception ex) {}
    }
  }
}

14.4 Formatiertes Lesen und Schreiben

14.5 Die Reader und Writer-Klassen

14.6 Serialisierung von Objekten

14.7 Die Klasse RandomAccessFile

Created with Vim Zurück   Weiter