Die Verwendung von RandomAccessFile soll an einem kleinen
Beispiel verdeutlicht werden. Es ist ein Programm,
das jedesmal, wenn es aufgerufen wird, einen Spruch auf die Standardausgabe ausgibt
(vergleichbar mit dem auf UNIX-Plattformen bekannten Programm fortune).
Der auszugebende Spruch soll durch einen Zufallsgenerator bestimmt werden, die Anzahl
der Sprüche soll variabel sein:
public class RandomAccessDemo {
public static void main(String args[])
throws IOException {
PrintWriter stdout =
new PrintWriter(System.out, true);
// Erzeugen des RandomAccessFiles
RandomAccessFile datafile =
new RandomAccessFile("sayings.dat","r");
// Zufallsposition in der Datei bestimmten
long pos = (long)(datafile.length()*Math.random());
// Dateizeiger an die Zufallsposition setzen
datafile.seek(pos);
// So lange den Dateizeiger rückwärts bewegen,
// bis ein Trennzeichen
// oder der Anfang der Datei erreicht wird
int key = datafile.read(); // Zeichenpuffer
while((pos != 0) && ((char)key != '*'))
datafile.seek(--pos);
// Lesen eines weiteren Zeichens, wenn
// nicht der Anfang erreicht wurde
if (pos != 0)
key = datafile.read();
// Ausgabe einer Leerzeile,
// Wenn der erste Spruch gesucht ist
if (pos == 0)
stdout.println();
// So viele Zeichen ausgeben, bis das Dateiende, oder
// der Beginn des nächsten Spruches erreicht wird
while(((key = datafile.read()) != (int)'*')
&& (key != -1))
stdout.print((char)key);
stdout.println();
datafile.close(); // Datei schließen
}
}
Wie man sehen kann, ist die Realisierung dieser Aufgabe nicht sehr umfangreich.
Auch bei der Klasse RandomAccessFile läßt es sich nicht vermeiden, ein Exemplar zu erzeugen:
RandomAccessFile datafile =
new RandomAccessFile("sayings.dat","r");
Im Unterschied zu File muss jedoch zusätzlich zum Dateinamen
der Zugriffsmodus angegeben werden. Der
Zugriffsmodus kann entweder nur lesend
(r), nur schreibend (w) oder lesend und schreibend (rw) sein.
Der Versuch, in eine als nur lesend geöffnete Datei zu schreiben, löst eine
IOException aus.
Nun wird der Programmcode analysiert:
long pos = (long)(datafile.length()*Math.random());
// Dateizeiger an die Zufallsposition setzen
datafile.seek(pos);
Um an eine bestimmte Stelle innerhalb der Datei zu springen,
besitzt RandomAccessFile
die Methode seek(long).
Der übergebene Parameter muss allerdings auch innerhalb des gültigen
Bereiches liegen. Um dies zu gewährleisten, wird vorher die Länge
der Datei mit file.length() abgefragt und mit einer
Zufallszahl zwischen 0 und 1 multipliziert
(das Ergebnis von Math.random()).
Das Pendant zu seek() stellt die Methode getFilePointer() dar.
Sie liefert die aktuelle Position
des Dateizeigers als Ergebnis. getFilePointer() wird in diesem Beispiel allerdings nicht benutzt.
Von der zufällig bestimmten Position aus wird die Datei rückwärts zeichenweise
ausgelesen, bis der Dateizeiger bei einem Stern oder dem Dateianfang angekommen ist:
int key = datafile.read(); // Zeichenpuffer
while((pos != 0) && ((char)key != '*'))
datafile.seek(--pos);
// Lesen eines weiteren Zeichens, wenn
// nicht der Anfang erreicht wurde
if (pos != 0)
key = datafile.read();
Die Ausgabe erfolgt analog dazu:
while(((key = datafile.read()) != (int)'*')
&& (key != -1))
stdout.print((char)key);
stdout.println();
datafile.close(); // Datei schließen
Ist die Ausgabe beendet, wird die Datei wieder geschlossen.
Bei der Auswahl des ersten Spruchs
muss man zwei Dinge berücksichtigen:
- Beim Suchen des Spruchanfangs darf kein Zeichen mehr eingelesen werden, wenn sich der Dateizeiger am Dateianfang befindet, da das erste Zeichen der Datei bereits zum ersten Spruch gehört.
- Um alle Sprüche im gleichen Format darzustellen, muss man eine
leere Zeile ausgeben. Das liegt daran, dass beim Suchen des Spruches
stets bis zum Trennungszeichen zurückgegangen wird. Alle folgenden Zeichen werden ausgegeben: Da nach dem Trennungszeichen in der Datei eine neue Zeile begonnen wird, folgt zuerst ein Newline-Zeichen. Am Anfang der Datei befindet sich jedoch kein solches Newline-Zeichen.
Ein
weiterer Unterschied der im Vergleich zu File auffällt, ist folgender:
Mit RandomAccessFile muss man nicht explizit einen Stream öffnen,
um auf die Datei zugreifen zu können. Dies wird automatisch beim Erzeugen
des Exemplars getan. So kann direkt über die Methoden von RandomAccessFile
in die Datei geschrieben werden.