„Wir beginnen mit Streams für die Dateieingabe und Dateiausgabe. Aber eins nach dem anderen.“

Es gibt zwei Klassen zum Lesen und Schreiben von Dateien: FileInputStream und FileOutputStream. Wie du wahrscheinlich schon erraten hast, kannst du mit FileInputStream Bytes nacheinander aus einer Datei lesen und mit FileOutputStream Bytes nacheinander in eine Datei schreiben. Hier siehst du die Methoden, die diese Klassen besitzen:

Methode Das tut die Methode
FileInputStream(String fileName);
– Das ist der Konstruktor. Hier kannst du den Namen einer Datei auf der Festplatte angeben, aus der das erzeugte Objekt Daten lesen wird.
int read();
– Diese Methode liest ein Byte aus der Datei und gibt es zurück. Der Rückgabewert wird auf ein int erweitert.
int available();
– Diese Methode gibt die Anzahl der ungelesenen (verfügbaren) Bytes zurück.
void close();
– Mit dieser Methode wird der Datenstrom „geschlossen“. Du rufst sie auf, wenn du die Arbeit mit dem Stream beendet hast.
Das Objekt führt dann die notwendigen Operationen aus, um die Datei zu schließen usw.
Zu diesem Zeitpunkt kannst du keine Daten mehr aus dem Stream lesen.

Nur so zum Spaß berechnen wir die Summe aller Bytes in einer Datei. So sieht der Code aus:

Alle Bytes in einer Datei summieren
public static void main(String[] args) throws Exception
{
 //Create a FileInputStream object bound to «c:/data.txt».
 FileInputStream inputStream = new FileInputStream("c:/data.txt");
 long sum = 0;

 while (inputStream.available() > 0) //as long as there are unread bytes
 {
  int data = inputStream.read(); //Read the next byte
  sum +=  data; //Add it to the running total
 }
 inputStream.close(); // Close the stream

 System.out.println(sum); // Display the sum on the screen.
}

„Wir haben uns bereits mit so etwas beschäftigt. Wie ist FileOutputStream aufgebaut?“

„OK. Sieh dir das an:“

Methode Das tut die Methode
FileOutputStream (String fileName);
„Das ist der Konstruktor. Hier kannst du den Namen einer Datei auf der Festplatte angeben, in die das erzeugte Objekt Daten schreiben wird.
void write(int data);
„Diese Methode schreibt das nächste Byte, wobei die Daten auf ein Byte abgeschnitten werden.“
void flush();
„Die zu schreibenden Daten werden oft zuerst in großen Blöcken im Speicher gesammelt und dann erst auf die Festplatte geschrieben.“

Der flush-Befehl erzwingt, dass alle ungespeicherten Informationen auf die Festplatte geschrieben werden.

void close();
„Diese Methode ‚schließt‘ den Datenstrom. Du rufst sie auf, wenn du die Arbeit mit dem Stream beendet hast.“
Das Objekt führt dann die notwendigen Operationen aus, um die Datei zu schließen usw.

Du kannst keine Daten mehr in den Stream schreiben, und flush wird automatisch aufgerufen.

„Das war‘s?“

„Ja, es gibt tatsächlich nur eine Methode zum Schreiben: write(). Sie schreibt jeweils nur ein Byte auf einmal. Aber du kannst so viele Informationen in die Datei schreiben, wie du willst.“

Beim Programmieren geht es darum, eine große und komplexe Aufgabe in viele kleine Aufgaben aufzuteilen. Im Wesentlichen geschieht hier genau das: Das Lesen und Schreiben großer Datenblöcke wird in Bit-große Teile aufgeteilt – jeweils ein Byte auf einmal.

So kannst du diese Klassen verwenden, um eine Datei auf die Festplatte zu kopieren:

Eine Datei auf die Festplatte kopieren
public static void main(String[] args) throws Exception
{
 //Create a stream to read bytes from a file
 FileInputStream inputStream = new FileInputStream("c:/data.txt");
 //Create a stream to write bytes to a file
 FileOutputStream outputStream = new FileOutputStream("c:/result.txt");

 while (inputStream.available() > 0) //as long as there are unread bytes
 {
  int data = inputStream.read(); // Read the next byte into the data variable
  outputStream.write(data); // and write it to the second stream
 }

 inputStream.close(); //Close both streams. We don't need them any more.
 outputStream.close();
}

„Danke, Ritschie. Endlich verstehe ich, wie dieser Code tatsächlich funktioniert.“