25.3 Schreiben in eine Datei und Lesen aus einer Datei
   
  Ein Rechner verwaltet nicht nur Daten, die während der Laufzeit des Programms erzeugt werden. Die meisten Programme greifen auf ältere Datenbestände zurück oder erzeugen für einen späteren Gebrauch Daten. Ein Javaprogramm muss also Daten in eine Datei schreiben oder aus einer Datei Daten lösen können. Wieder benutzen wir die gleiche Technik: Beim Schreiben in eine Datei speist das Javaprogramm die zu sichernden Daten in ein Pipeline, die das System wieder ausliest und in eine Datei z.B. auf eine Festplatte speichert. Schauen wir uns das in einem Beispielprogramm an.:
Download:
SchreibeInDatei. java
 
import java.io.*;

public class SchreibeInDatei {

  public static void main (String[] args) throws IOException{
    String text = "Dieser Text wird in einer Datei gespeichert!";
    String dateiName = "Test.txt";
    FileOutputStream schreibeStrom = 
                     new FileOutputStream(dateiName);
    for (int i=0; i < text.length(); i++){
      schreibeStrom.write((byte)text.charAt(i));
    }
    schreibeStrom.close();
    System.out.println("Datei ist geschrieben!");
  }
}
Ausgabe Nachdem das Programm abgearbeitet ist, man erkennt dies daran, dass auf dem Bildschirm die Ausgabe "Datei ist geschrieben!" erscheint, gibt es in dem Verzeichnis, in dem das Programm gespeichert ist eine Datei mit dem Namen Test.txt. Öffnen wir diese Datei mit dem Standard-Editor von Windows, so sehen wir den gespeicherten Text.
 
 

Ist das tatsächlich so, dass der Text in der Datei steht? Wir analysieren unser Programm und werden dabei versuchen diese Frage zu beantworten. Die Pipeline zwischen dem Javaprogramm und dem System ist sehr einfach gebaut. Sie verlangt dass die Daten als bytes eingespeist werden. Das Rechnersystem liest aus der Pipeline die Daten auch wieder in 1 Byte großen Blöcken und speichert diesen Code auf die Platte, wobei der Dateiname das System von dem Javaprogramm mitgeteilt bekommen muss. In

FileOutputStream schreibeStrom =
                 new
FileOutputStream(dateiName);
 

  wird ein Ausgabestrom-Objekt schreibeStrom der Klasse FileInputStream erzeugt. Als Parameter wird dem Konstruktor der Name der Datei als String übergeben. Der Dateiname ist dabei vollkommen willkürlich. An Stelle von Test.txt hätte man genauso gut mein.bla oder Test.jpg wählen können. Warum wir es nicht tun, werden wir später sehen. Nachdem die Pipeline angelegt ist, müssen wir nur noch die Daten in die Pipeline einspeisen. Dazu benutzen wird die Methode write(byte paket) der Klasse FileOutputStream.
 
  schreibeStrom.write((byte)text.charAt(i));
 
  Es wird aus dem Text, den wir speichern wollen ein Zeichen (char) gelesen (text.charAt(i)), explizit zu einem byte gecastet und danach in die Pipeline geschrieben. Ist der ganze in der Pipeline, wir benutzen dazu eine Schleife, schließen wir die Pipeline mit der close()-Methode, das Rechnersystem übernimmt die Kontrolle liest aus der Pipeline die Daten (im Prinzip nichts anderes als eine Reihung von Nullen und Einsen) schreibt sie in die Datei auf der Festplatte und gibt die Kontrolle an das Javaprogramm zurück.
 
  Klicken wir von Windows aus auf die Datei Test.txt, so wird die Datei vom Standard-Editor geöffnet, denn bei einer 'txt'-Endung 'geht Windows geht davon aus', dass es sich um eine einfache Textdatei handelt. Wie geschieht es, dass der Editor den Inhalt der Datei 'Test.txt' auch als Text auf den Bildschirm schreibt? Nun das ist jetzt einfach: Der Editor, der ja davon ausgeht, dass es sich bei der Datei um eine Textdatei handelt, liest aus der Datei 1 Byte große Blöcke, interpretiert ihren Inhalt als ASCII-Zeichen und schreibt das zum Zahlenwert gehörige Zeichen auf den Bildschirm. Der Windows-Editor benutzt zum Auslesen der Datei ebenfalls einen Eingabestrom. Und woher weiß der Editor wann, das Ende des Datenstroms gekommen ist und deshalb nicht über das Ende hinaus liest? Es gibt in der Datei tatsächlich eine Endemarkierung, die beim Schreiben der Datei vom System hinzugefügt wurde.

Wir wollen diesen Sachverhalt genauer untersuchen indem wir ein Javaprogramm schreiben, das eine Datei ausliest.
 

Download:
LeseAusDatei. java
import java.io.*;

public class LeseAusDatei {

  public static void main (String[] args) throws IOException{
     byte zeichen;
     char buchstabe;
     String text = "";
     String dateiName = "Test.txt";
     FileInputStream leseStrom = new FileInputStream(dateiName);
     do{
       zeichen = (byte)leseStrom.read();
       System.out.print(zeichen+" ");
       text += (char)zeichen;
     } while (zeichen !=-1);
     leseStrom.close();
     System.out.println();
     System.out.println(text);
  }
}
  Statt einer Ausgabe-Pipeline benutzen wir eine EingabePipeline, die in einem FileInputStream-Objekt nämlich leseStrom verwaltet wird. Mit der read()-Methode werden aus der Ausgabe-Pipeline 1 Byte große Pakete gelesen. die read() als int-Werte an das aufrufende Javaprogramm liefert, wo sie nach einem expliziten Cast in der byte-Variablen zeichen gespeichert werden. Zur Kontrolle werden diese Zeichen ausgegeben. Ein weiterer expliziten Typenumwandlung castet den Inhalt von zeichen zu in einem char. Schließlich wird die ganze Zeichenkette aufgebaut und schließlich ausgegeben.
 
  68 105 101 115 101 114 32 84 101 120 116 32 119 105 114 100 32 105 110 32 101 105 110 101 114 32 68 97 116 101 105 32 103 101 115 112 101 105 99 104 101 114 116 33 -1
Dieser Text wird in einer Datei gespeichert!?
 
  Wir erkennen also, was tatsächlich in der Textdatei stand und dass erst die Interpretation einen Text daraus macht. Und noch ein weiteres zeigt die Ausgabe: Das letzte Zeichen in der Datei ist '-1' als Byte-Zeichen! Es übernimmt die Rolle von 'Der letzte macht die Tür zu'. Jetzt verstehen wir auch die Abbruchbedingung in unserer do-while-Schleife. Interpretieren wir dieses Schlusszeichen als char-Zeichen, dann wird daraus ein '?'-Zeichen. Der Windows-Editor gibt dieses Schlusszeichen nicht aus. Ein etwas modifiziertes Javaprogramm würde das gleiche leisten.
   
zu den 25.4 Übungen
zur Startseite www.pohlig.de  (C) MPohlig 2005