![]() |
|
|
Ist der Parameter append nicht mit true belegt, wird der alte Inhalt überschrieben. Das nachfolgende Programm erfragt über einen grafischen Dialog eine Eingabe und schreibt diese in eine Datei: Listing 12.8 BenutzereingabeSchreiben.java import java.io.*; import javax.swing.JOptionPane; public class BenutzereingabeSchreiben { public static void main( String args[] ) { byte buffer[] = new byte[80]; try { String s; while ( ( s = JOptionPane.showInputDialog( "Gib eine nette Zeile ein:" )) = = null ); FileOutputStream fos = new FileOutputStream( "c:/line.txt" ); fos.write( s.getBytes() ); fos.close(); } catch ( Exception e ) { System.out.println(e); } } } 12.4.4 Die Eingabeklasse InputStream
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
abstract class java.io. InputStream implements Closeable |
| int available() Gibt die Anzahl der verfügbaren Zeichen im Datenstrom zurück, die sofort ohne Blockierung gelesen werden können. |
| int read() Liest ein Byte als Integer aus dem Datenstrom. Ist das Ende des Datenstroms erreicht, wird –1 übergeben. Die Funktion ist überladen, wie die nächsten Signaturen zeigen. |
| int read( byte b[] ) Mehrere Bytes werden in ein Feld gelesen. Die tatsächliche Länge der gelesenen Bytes wird zurückgegeben. |
| int read( byte b[], int off, int len ) Liest den Datenstrom in ein Bytefeld, schreibt ihn aber erst an der Stelle off in das Bytefeld. Zudem begrenzt len die maximale Anzahl von zu lesenden Zeichen. |
| long skip( long n ) Überspringt eine Anzahl von Zeichen. |
| void mark( int readlimit ) Merkt sich eine Position im Datenstrom. |
| boolean markSupported() Gibt einen Wahrheitswert zurück, ob der Datenstrom das Merken und Zurücksetzen von Positionen gestattet. Diese Markierung ist ein Zeiger, der auf bestimmte Stellen in der Eingabedatei zeigen kann. |
| void reset() Springt wieder zurück zur Position, die mit mark() gesetzt wurde. |
| void close() Schließt den Datenstrom. Operation aus der Schnittstelle Closeable. |
Gelingt eine Durchführung nicht, bekommen wir eine IOException.
Bisher haben wir die grundlegenden Ideen der Stream-Klassen kennen gelernt, aber noch kein echtes Beispiel. Dies soll sich nun ändern. Wir wollen für einfache Dateieingaben die Klasse FileInputStream verwenden (FileInputStream implementiert InputStream). Wir binden mit dieser Klasse eine Datei (etwa repräsentiert als ein Objekt vom Typ File) an einen Datenstrom.

Hier klicken, um das Bild zu Vergrößern
class java.io. FileInputStream extends InputStream |
Um ein Objekt anzulegen, haben wir die Auswahl zwischen drei Konstruktoren:
| FileInputStream( String name ) Erzeugt einen FileInputStream mit einem gegebenen Dateinamen. Der richtige Dateitrenner, zum Beispiel »\« oder »/«, sollte beachtet werden. |
| FileInputStream( File file ) Erzeugt FileInputStream aus einem File-Objekt. |
| FileInputStream( FileDescriptor fdObj ) Erzeugt FileInputStream aus einem FileDescriptor-Objekt. |
Ein Programm, welches seinen eigenen Quellcode anzeigt, sieht wie folgt aus:
Listing 12.9 ReadQuellcode.java
import java.io.*; public static void main ( String args[] ) { String filename = "ReadQuellcode.java"; byte buffer[] = new byte[ 4000 ]; FileInputStream in = null; try { in = new FileInputStream( filename ); int len = in.read( buffer, 0, 4000 ); String str = new String( buffer, 0, len ); System.out.println( str ); } catch ( IOException e ) { System.out.println( e ); } finally { try { if ( in != null ) in.close(); } catch (IOException e) {} } } }
Zunächst reserviert das Programm ein fixes Bytefeld mit 4 KB. Anschließend wird versucht, 4.000 Zeichen in das Bytefeld einzulesen. Die genaue Anzahl der gelesenen Zeichen liefert die Rückgabe von read(). Anschließend wird das Bytefeld in ein String konvertiert und dieser ausgegeben.
Um die gesamte Datei einzulesen, müssen wir vorher die Dateigröße kennen. Dazu lässt sich length() der File-Klasse nutzen. Und wenn ein File-Objekt sowieso schon angelegt ist, lässt sich damit auch gleich die Datei öffnen.
File f = new File( Dateiname ); byte buffer[] = new byte[ (int) f.length() ]; in = new FileInputStream( f );
Die Klasse java.io.FileDescriptor repräsentiert eine offene Datei oder eine Socket-Verbindung mittels eines Deskriptors. Er lässt sich bei File-Objekten mit getFD() erfragen; bei Socket-Verbindungen allerdings nicht über eine Funktion – nur Unterklassen von SocketImpl (und DatagramSocketImpl) ist der Zugriff auf eine protected Methode getFileDescriptor() zugesagt.
In der Regel kommt der Entwickler nicht mit einem FileDescriptor-Objekt in Kontakt. Es gibt allerdings eine Anwendung, in der die Klasse FileDescriptor nützlich ist: Sie bietet eine sync()-Funktion an, die verbleibende Speicherblöcke auf das Gerät schreibt. Damit lässt sich erreichen, dass Daten auch tatsächlich auf dem Datenträger materialisiert werden.
Neben FileInputStream kennen auch FileOutputStream und RandomAccessFile eine Funktion getFD(). Mit einem FileDescriptor kann auch die Arbeit zwischen Stream-Objekten und RandomAccessFile-Objekten koordiniert werden.
Als Beispiel für das Zusammenspiel von FileInputStream und FileOutputStream wollen wir nun ein Datei-Kopierprogramm entwerfen. Es ist einleuchtend, dass wir zunächst die Quelldatei öffnen müssen. Taucht ein Fehler auf, wird dieser zusammen mit allen anderen Fehlern in einer besonderen IOException-Fehlerbehandlung ausgegeben. Wir trennen hier die Fehler nicht besonders. Nach dem Öffnen der Quelle wird eine neue Datei angelegt. Das machen wir einfach mit FileOutputStream. Der Methode ist es jedoch ziemlich egal, ob es schon eine Datei mit diesem Namen gibt, da sie diese gnadenlos überschreibt. Auch darum kümmern wir uns nicht. Wollten wir das berücksichtigen, sollten wir mit Hilfe der File-Klasse die Existenz einer Datei mit dem gleichen Namen prüfen. Doch wenn alles glatt geht, lassen sich die Bytes kopieren. Der naive und einfachste Weg liest jeweils ein Byte ein und schreibt dieses.
Es muss nicht extra erwähnt werden, dass die Geschwindigkeit dieses Ansatzes erbärmlich ist. Das Puffern in einen BufferedInputStream beziehungsweise Ausgabestrom ist in diesem Fall unnötig, da wir einfach einen Puffer mit read(byte[]) füllen können. Da diese Methode die Anzahl tatsächlich gelesener Bytes zurückliefert, schreiben wir diese direkt mittels write() in den Ausgabepuffer. Hier bringt eine Pufferung über eine Zwischen-Puffer-Klasse keine zusätzliche Geschwindigkeit ein, da wir ja selbst einen 64 KB-Puffer einrichten.
Listing 12.10 FileCopy.java
import java.io.*; public class FileCopy { static void copy( String src, String dest ) { try { copy( new FileInputStream( src ), new FileOutputStream( dest ) ); } catch( IOException e ) { System.err.println( e ); } } static void copy( InputStream fis, OutputStream fos ) { try { byte buffer[] = new byte[0xffff]; int nbytes; while ( (nbytes = fis.read(buffer)) != –1 ) fos.write( buffer, 0, nbytes ); } catch( IOException e ) { System.err.println( e ); } finally { if ( fis != null ) try { fis.close(); } catch ( IOException e ) {} try { if ( fos != null ) fos.close(); } catch ( IOException e ) {} } } public static void main( String args[] ) { if ( args.length < 2 ) System.out.println( "Usage: java FileCopy <src> <dest>" ); else copy( args[0], args[1] ); } }
| << zurück |
Copyright © Galileo Press GmbH 2004
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.