10.5.1 | Elementare Dateiein- und -ausgabe |
Folgendes Beispiel liest einen Text von der Standardeingabe ein und speichert ihn in einer Datei, bis ein x eingegeben wird. Anschließend wird diese Datei ausgelesen und ihr Inhalt auf der Standardausgabe ausgegeben:import java.io.*; public class FileDemo { final static String name = "FileDemo.dat"; public static void main(String args[]) { File textFile; // Textdatei FileReader in; // Dateieingabe-Stream FileWriter out; // Dateiausgabe-Stream // Standardeingabe in Reader umwandeln BufferedReader stdin; stdin = new BufferedReader( new InputStreamReader(System.in)); PrintWriter stdout=new PrintWriter(System.out,true); // Erzeugen eines Ausgabe-Streams, der mit der Datei // 'FileDemo.dat' verknüpft ist try { out = new FileWriter(name); int key = 0; // Einlesen von Text von der Standardeingabe // bis zur Eingabe eines x und // gleichzeitiges Abspeichern des Textes do { try { key = stdin.read(); out.write(key); } catch(IOException e) { e.printStackTrace(); } } while((char)key != 'x'); out.close(); // Schließen der Datei // Erzeugen eines Eingabe-Streams, der mit // der Datei verknüpft ist textFile = new File(name); in = new FileReader(textFile); int size = (int)textFile.length(); // Dateilänge int read = 0; // Anzahl der gelesenen Zeichen char data[] = new char[size]; // Lesepuffer // Auslesen der Datei while (read < size) read =+ (byte)in.read(data, read, size-read); in.close(); // Ausgabe des Lesepuffers stdout.println(new String(data)); } catch (IOException ex) { ex.printStackTrace(); } } }Um in eine bestimmte Datei schreiben zu können, muss zuerst eine Verknüpfung zwischen der Datei und ihrem Namen hergestellt werden. Hierzu existieren zwei Möglichkeiten:Obiges Beispiel verwendet beide Varianten. Bei der Dateiausgabe wird der Dateiname direkt über FileWriter mit der Datei verknüpft:
- über ein File-Objekt
- direkt über die Klassen FileReader und FileWriter bzw. FileInputStream und FileOutputStream
out = new FileWriter(name);Das Anlegen eines Streams zum Lesen einer Datei erfolgt entsprechend durch Erzeugen eines Exemplars von FileReader. Der Zugriff auf die Datei erfolgt analog zum Schreiben bzw. Lesen in andere Streams.
Werden auf diese Art Dateien mit Streams verknüpft, kann man aber nur aus der Datei lesen bzw. in die Datei schreiben. Man hat keine Zugriffsmöglichkeit auf die Attribute wie z. B. Lesbarkeit oder die Größe einer Datei.
Zum Einlesen einer Datei kann es z. B. hilfreich sein, die Größe einer Datei zu kennen. Deshalb wird im obigen Beispiel ebenfalls ein Exemplar von File verwendet:textFile = new File(name);Dem Konstruktor von File wird in diesem Fall nur der Name der Datei übergeben (relative Angabe). Die Datei wird vom Java-Interpreter im aktuellen Verzeichnis gesucht. name könnte aber genau so gut eine absolute Pfadangabe enthalten. Die Angabe kann auch relativ zu einer bereits geöffneten Datei erfolgen:otherFile = new File(myFile, name);In obiger Zeile stellt myFile eine Referenz auf ein File-Objekt dar. Der Interpreter sucht die Datei name in dem Verzeichnis, in welchem die Datei myFile liegt, unabhängig vom aktuellen Verzeichnis.
Die Größe der Datei kann anschließend mit der Methode length() der Klasse File ermittelt werden:int size = (int)textFile.length(); // DateilängeDadurch, dass man die Größe einer Datei kennt, kann man genau so viele Zeichen lesen, wie sich tatsächlich in der Datei befinden. Man muss also nicht abfragen, ob man sich am Dateieinde befindet:while (read < size) read =+ (byte)in.read(data, read, size-read);Würde man nicht die Dateigröße abfragen, müsste man so lange lesen, bis das Ende der Datei erreicht wird. Kann kein Zeichen mehr gelesen werden, liefert read(char[], int, int) das Ergebnis -1. Die Einlesesequenz hätte dann folgende Gestalt:int z; while((z = in.read()) != -1 ) stdout.print((char)z);Die Datei wird zeichenweise ausgelesen, bis man sich am Dateiende befindet. In diesem Fall liefert read() -1 als Ergebnis. Dieses Prinzip wurde auch schon beim Auslesen des SequenceInputStreams angewendet.
Nachdem die Datei ausgelesen wurde, wird der Stream wieder geschlossen:in.close();Die einzelnen Möglichkeiten, die sich dem Benutzer durch die Verwendung der Klasse File bieten, werden im nächsten Abschnitt ausführlich beschrieben. Beim Öffnen von Dateien auf Windows-Plattformen gibt es eine kleine Besonderheit: Ist die zu öffnende Datei bereits von einer anderen Anwendung in Benutzung, wird eine FileNotFoundException ausgelöst. Deshalb sollte man sich beim Auftreten dieses Fehlers ebenfalls vergewissern, ob die Datei nicht bereits offen ist.