Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger

 << zurück
Java ist auch eine Insel von Christian Ullenboom
Programmieren für die Java 2-Plattform in der Version 5
Java ist auch eine Insel

Java ist auch eine Insel
5., akt. und erw. Auflage
1454 S., mit CD, 49,90 Euro
Galileo Computing
ISBN 3-89842-747-1
gp Kapitel 12 Datenströme und Dateien
  gp 12.1 Datei und Verzeichnis
    gp 12.1.1 Dateien und Verzeichnisse mit der Klasse File
    gp 12.1.2 Dateieigenschaften und -attribute
    gp 12.1.3 Änderungsdatum einer Datei, Nur-Lese-Rechte setzen
    gp 12.1.4 Dateien berühren, neue Dateien anlegen, temporäre Dateien
    gp 12.1.5 Umbenennen und Verzeichnisse anlegen
    gp 12.1.6 Die Wurzel aller Verzeichnisse/Laufwerke
    gp 12.1.7 Verzeichnisse listen und Dateien filtern
    gp 12.1.8 Dateien und Verzeichnisse löschen
    gp 12.1.9 Verzeichnisse nach Dateien rekursiv durchsuchen
    gp 12.1.10 Namen der Laufwerke
    gp 12.1.11 URL- und URI-Objekte aus einem File-Objekt ableiten
    gp 12.1.12 Locking
    gp 12.1.13 Sicherheitsprüfung
    gp 12.1.14 Implementierungsmöglichkeiten für die Klasse File
    gp 12.1.15 Mime-Typen
  gp 12.2 Dateien mit wahlfreiem Zugriff
    gp 12.2.1 Ein RandomAccessFile zum Lesen und Schreiben öffnen
    gp 12.2.2 Aus dem RandomAccessFile lesen
    gp 12.2.3 Schreiben
    gp 12.2.4 Die Länge des RandomAccessFile
    gp 12.2.5 Hin und her in der Datei
    gp 12.2.6 Wahlfreier Zugriff und Pufferung mit Unified I/O
  gp 12.3 Stream-Klassen und Reader/Writer
    gp 12.3.1 Die abstrakten Basisklassen
    gp 12.3.2 Übersicht über Ein-/Ausgabeklassen
  gp 12.4 Binäre Ein-/Ausgabe-Klassen InputStream/OutputStream
    gp 12.4.1 Die abstrakte Basisklasse OutputStream
    gp 12.4.2 Die Schnittstellen Closeable und Flushable
    gp 12.4.3 Ein Datenschlucker
    gp 12.4.4 Anwendung der Klasse FileOutputStream
    gp 12.4.5 Die abstrakte Eingabeklasse InputStream
    gp 12.4.6 Ressourcen wie Grafiken aus dem Klassenpfad und aus Jar–Archiven laden
    gp 12.4.7 Anwenden der Klasse FileInputStream
    gp 12.4.8 Kopieren von Dateien
    gp 12.4.9 Das FileDescriptor-Objekt
  gp 12.5 PrintStream und Konsolenausgaben
    gp 12.5.1 Die Klasse PrintStream
    gp 12.5.2 Die Schnittstelle Appendable
    gp 12.5.3 System.in und System.out
    gp 12.5.4 Ströme umlenken
    gp 12.5.5 Den Bildschirm löschen und Textausgaben optisch aufwerten
  gp 12.6 Daten filtern durch FilterInputStream und FilterOutputStream
    gp 12.6.1 DataOutputStream/DataInputStream
  gp 12.7 Besondere OutputStream- und InputStream-Klassen
    gp 12.7.1 Mit ByteArrayOutputStream in ein Byte-Feld schreiben
    gp 12.7.2 Mit ByteArrayInputStream aus einem Byte-Feld lesen
    gp 12.7.3 Ströme zusammensetzen mit SequenceInputStream
  gp 12.8 Die Unterklassen von Writer
    gp 12.8.1 Die abstrakte Basisklasse Writer
    gp 12.8.2 Ausgabemöglichkeiten durch PrintWriter erweitern
    gp 12.8.3 Datenkonvertierung durch den OutputStreamWriter
    gp 12.8.4 In Dateien schreiben mit der Klasse FileWriter
    gp 12.8.5 StringWriter und CharArrayWriter
    gp 12.8.6 Writer als Filter verketten
    gp 12.8.7 Gepufferte Ausgabe durch BufferedWriter
    gp 12.8.8 Daten mit FilterWriter filtern
  gp 12.9 Die Klassen um Reader
    gp 12.9.1 Die abstrakte Basisklasse Reader
    gp 12.9.2 Automatische Konvertierungen mit dem InputStreamReader
    gp 12.9.3 Dateien lesen mit der Klasse FileReader
    gp 12.9.4 StringReader und CharArrayReader
  gp 12.10 Die Filter für Zeichenströme
    gp 12.10.1 Gepufferte Eingaben mit der Klasse BufferedReader
    gp 12.10.2 LineNumberReader zählt automatisch Zeilen mit
    gp 12.10.3 Eingaben filtern mit der Klasse FilterReader
    gp 12.10.4 Daten mit der Klasse PushbackReader zurücklegen
  gp 12.11 Kommunikation zwischen Threads mit Pipes
    gp 12.11.1 PipedOutputStream und PipedInputStream
    gp 12.11.2 PipedWriter und PipedReader
  gp 12.12 Datenkompression
    gp 12.12.1 Java-Unterstützung beim Komprimieren und Zusammenpacken
    gp 12.12.2 Datenströme komprimieren
    gp 12.12.3 Zip-Archive
    gp 12.12.4 Jar-Archive
  gp 12.13 Prüfsummen
    gp 12.13.1 Die Schnittstelle Checksum
    gp 12.13.2 Die Klasse CRC32
    gp 12.13.3 Die Adler32-Klasse
  gp 12.14 Persistente Objekte und Serialisierung
    gp 12.14.1 Objekte speichern mit der Standard-Serialisierung
    gp 12.14.2 Objekte über die Standard-Serialisierung lesen
    gp 12.14.3 Die Schnittstelle Serializable
    gp 12.14.4 Nicht serialisierbare Attribute mit transient aussparen
    gp 12.14.5 Das Abspeichern selbst in die Hand nehmen
    gp 12.14.6 Tiefe Objektkopien
    gp 12.14.7 Versionenverwaltung und die SUID
    gp 12.14.8 Wie die ArrayList serialisiert
    gp 12.14.9 Probleme mit der Serialisierung
    gp 12.14.10 Serialisieren in XML-Dateien
    gp 12.14.11 JavaBeans Persistence
    gp 12.14.12 XStream
  gp 12.15 Zugriff auf SMB-Server
    gp 12.15.1 jCIFS
  gp 12.16 Tokenizer
    gp 12.16.1 StreamTokenizer
    gp 12.16.2 CSV (Comma Separated Values)-Dateien verarbeiten
  gp 12.17 Die Logging-API


Galileo Computing

12.4 Binäre Ein-/Ausgabe-Klassen InputStream/OutputStreadowntop

Die Klassen InputStream und OutputStream bilden die Basisklassen für alle Byte-orientierten Klassen und dienen somit als Bindeglied bei Funktionen, die als Parameter ein Eingabe- und Ausgabe-Objekt verlangen. So ist ein InputStream nicht nur für Dateien denkbar, sondern auch für Daten, die über das Netzwerk kommen.


Galileo Computing

12.4.1 Die abstrakte Basisklasse OutputStream  downtop

Der Clou bei allen Datenströmen ist nun, dass spezielle Unterklassen wissen, wie sie genau die vorgeschriebene Funktionalität implementieren. Wenn wir uns den OutputStream anschauen, dann sehen wir auf den ersten Blick, dass hier alle wesentlichen Operationen um das Schreiben versammelt sind. Das heißt, dass ein konkreter Stream, der in Dateien schreibt, nun weiß, wie er Byte in Dateien schreiben wird. (Natürlich ist hier auch Java mit seiner Plattformunabhängigkeit am Ende, und es werden native Methoden eingesetzt.)


abstract class java.io.  OutputStream
  implements CloseableFlushable

gp  abstract void write( int b ) throws IOException Schreibt ein einzelnes Byte in den Datenstrom.
gp  void write( byte[] b ) throws IOException Schreibt die Bytes aus dem Array in den Strom.
gp  void write( byte[] b, int off, int len ) throws IOException Liest len-Byte ab Position off aus dem Array und schreibt ihn in den Ausgabestrom.
gp  void close() throws IOException Schließt den Datenstrom. Einzige Methode aus Closeable.
gp  void flush() throws IOException Gepufferte Daten werden geschrieben. Einzige Methode aus der Schnittstelle Flushable.

Die IOException ist keine RuntimeException, muss also behandelt werden.

Zwei Eigenschaften lassen sich an den Methoden ablesen: zum einen, dass nur Bytes geschrieben werden, und zum anderen, dass nicht wirklich alle Methoden abstract sind. Zur ersten Eigenschaft: Wenn nur Bytes geschrieben werden, bedeutet dies, dass andere Klassen Erstere erweitern können, denn eine Ganzzahl ist nichts anderes als mehrere Bytes in einer geordneten Folge.

Nicht alle diese Methoden sind wirklich elementar, müssen also nicht von allen Ausgabeströmen überschrieben werden. Wir entdecken, dass nur write(int) abstrakt ist. Das würde aber bedeuten, dass alle anderen konkret wären. Gleichzeitig stellt sich die Frage, wie ein OutputStream, der die Eigenschaften für alle erdenklichen Ausgabeströme vorschreibt, denn wissen kann, wie ein spezieller Ausgabestrom etwa geschlossen (close()) wird oder seine gepufferten Bytes schreibt (flush()). Das weiß er natürlich nicht, aber die Entwickler haben sich dazu entschlossen, eine leere Implementierung anzugeben. Der Vorteil liegt darin, dass Programmierer von Unterklassen nicht verpflichtet werden, immer die Methoden zu überschreiben, auch wenn sie sie gar nicht nutzen wollen.

Über konkrete und abstrakte Schreibmethoden

Es fällt auf, dass es zwar drei Schreibmethoden gibt, aber nur eine davon wirklich abstrakt ist. Das ist trickreich, denn tatsächlich lassen sich die Methoden, die ein Bytefeld schreiben, auf die Methode, die ein einzelnes Byte schreibt, abbilden. Wir werfen einen Blick in den Quellcode der Bibliothek:

public void write(byte<span class="listing">[]</span> b) throws IOException {
  write(b0b.length);
}
public void write(byte<span class="listing">[]</span> bint offint len) throws IOException {
  if (b == null)
    throw new NullPointerException();
  else if ((off < 0) || (off > b.length) || (len < 0) ||
    ((off + len) > b.length) || ((off + len) < 0)) {
    throw new IndexOutOfBoundsException();
  } else if (len == 0)
    return;
  for (int i = 0 ; i < len ; i++)
    write(b[off + i]);
}

An beiden Implementierungen ist zu erkennen, dass sie die Arbeit sehr bequem an andere Methoden verschieben. Doch diese Implementierung ist nicht optimal! Stellen wir uns vor, ein Dateiausgabestrom überschreibt nur die eine abstrakte Methode, die nötig ist. Und nehmen wir weiterhin an, dass unser Programm nun immer ganze Bytefelder schreibt, etwa eine 5 MB-Datei, die im Speicher steht. Dann werden für jedes Byte im Byte-Array in einer Schleife alle Bytes der Reihe nach an eine vermutlich native Methode übergeben. Wenn es so implementiert wäre, könnten wir die Geschwindigkeit des Mediums überhaupt nicht nutzen, zumal jedes Dateisystem Funktionen bereitstellt, mit denen sich ganze Blöcke übertragen lassen. Glücklicherweise sieht die Implementierung nicht so aus, denn wir haben in dem Modell vergessen, dass die Unterklasse zwar die abstrakte Methode implementieren muss, aber immer noch andere Methoden überschreiben kann. Ein späterer Blick auf die Klasse FileOutputStream bestätigt dies.


Hinweis   Ruft eine Oberklasse eine abstrakte Methode auf, die in der Unterklasse implementiert wird, ist das ein Entwurfsmuster mit dem Namen Schablonen-Muster engl. Template-Pattern.


Galileo Computing

12.4.2 Die Schnittstellen Closeable und Flushable  downtop

Closeable und Flushable sind zwei sehr einfache Schnittstellen seit Java 5. Closeable wird von allen lesenden und schreibenden Datenstrom-Klassen implementiert, die geschlossen werden können.


class java.io.  Closeable  

gp  void close() throws IOException Schließt den Datenstrom. Ein schon geschlossener Strom kann noch einmal geschlossen werden und hat keine Konsequenzen.

Flushable findet sich nur bei allen schreibenden Klassen, und ist insbesondere bei denen wichtig, die Daten Puffern.


class java.io.  Flushable  

gp  void flush() throws IOException Schreibt gepufferte Daten in den Strom.

Galileo Computing

12.4.3 Ein Datenschlucker  downtop

Damit wir sehen können, wie alle Unterklassen prinzipiell mit OutputStream umgehen, wollen wir eine Klasse entwerfen, die alle Daten verwirft, die ihr gesendet werden. Die Klasse ist vergleichbar mit dem Unix-Device /dev/null. Die Implementierung ist die einfachste, die sich denken lässt, denn alle write()-Methoden machen nichts.

Listing 12.8   NullOutputStream.java

import java.io.OutputStream;
public final class NullOutputStream extends OutputStream
{
  @Override public void write( byte[] b ) { /* Empty */ }
  @Override public void write( byte[] bint offint len ) { /* Empty */ }
  @Override public void write( int b ) { /* Empty */ }
}

Da close() und flush()ohnehin schon mit einem leeren Block implementiert sind, brauchen wir sie nicht noch einmal zu überschreiben. Aus Effizienzgründen (!) geben wir auch eine Implementierung für die Schreib-Feld-Methoden an.


Galileo Computing

12.4.4 Anwendung der Klasse FileOutputStream  downtop

Diese Klasse FileOutputStream bietet grundlegende Schreibmethoden, um in Dateien zu schreiben. FileOutputStream implementiert alle nötigen Methoden, die OutputStream vorschreibt.


class java.io.  FileOutputStream
  extends OutputStream

gp  FileOutputStream( String name ) throws FileNotFoundException Erzeugt einen FileOutputStream mit einem gegebenen Dateinamen.
gp  FileOutputStream( File file ) throws FileNotFoundException Erzeugt einen FileOutputStream aus einem File-Objekt.
gp  FileOutputStream( String name, boolean append ) throws FileNotFoundException Wie FileOutputStream(name), hängt jedoch bei append=true Daten an.
gp  FileOutputStream( File file, boolean append ) throws FileNotFoundException Wie FileOutputStream(file), hängt jedoch bei append=true Daten an.
gp  FileOutputStream( FileDescriptor fdObj ) Erzeugt einen FileOutputStream aus einem FileDescriptor-Objekt.

Ist der Parameter append nicht mit true belegt, wird der alte Inhalt überschrieben. Die FileNotFoundException wirkt vielleicht etwas komisch, wird aber dann ausgelöst, wenn zum Beispiel die Dateiangabe ein Verzeichnis repräsentiert oder die Datei gelockt ist.

Das nachfolgende Programm erfragt über einen grafischen Dialog eine Eingabe und schreibt diese in eine Datei:

Listing 12.9   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 ); }
  }
}

Galileo Computing

12.4.5 Die abstrakte Eingabeklasse InputStream  downtop

Das Gegenstück zu OutputStream ist InputStream; jeder binäre Eingabestrom wird durch die abstrakte Klasse InputStream repräsentiert. Die Konsoleneingabe System.in ist vom Typ InputStream.


abstract class java.io.  InputStream
  implements Closeable

gp  int available() throws IOException Gibt die Anzahl der verfügbaren Zeichen im Datenstrom zurück, die sofort ohne Blockierung gelesen werden können.
gp  int read() throws IOException 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.
gp  int read( byte[] b ) throws IOException Mehrere Byte werden in ein Feld gelesen. Die tatsächliche Länge der gelesenen Bytes wird zurückgegeben.
gp  int read( byte[] b, int off, int len ) throws IOException Liest den Datenstrom in ein Bytefeld, schreibt ihn aber erst an der Stelle off in das Bytefeld. Zudem begrenzt len die maximale Anzahl der zu lesenden Zeichen.
gp  long skip( long n ) throws IOException Überspringt eine Anzahl von Zeichen.
gp  void close() throws IOException Schließt den Datenstrom. Operation aus der Schnittstelle Closeable.
gp  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.
gp  void mark( int readlimit ) Merkt sich eine Position im Datenstrom.
gp  void reset() throws IOException Springt wieder zurück zur Position, die mit mark() gesetzt wurde.

Auffällig ist, dass bis auf mark() und markSupported() alle Methoden im Fehlerfall eine IOException auslösen.


Hinweis   available() liefert die Anzahl Byte, die ohne Blockierung gelesen werden können. (Blockieren bedeutet, dass die Methode nicht sofort zurückkehrt, sondern erst wartet, bis neue Daten vorhanden sind.) Die Rückgabe von available() sagt nichts darüber aus, wie viele Zeichen der InputStream insgesamt hergibt. Während aber bei FileInputStream die Methode available() üblicherweise doch die Dateilänge liefert, ist dies bei den Netzwerk-Streams im Allgemeinen nicht der Fall.


Galileo Computing

12.4.6 Ressourcen wie Grafiken aus dem Klassenpfad und aus Jar–Archiven laden  downtop

Um Ressourcen wie Grafiken oder Konfigurationsdateien aus Jar-Archiven zu laden, ist die Methode getResourceAsStream() beziehungsweise getResource() ideal. Sie sind Methoden des Class-Objekts. getResource() gibt ein URL-Objekt für die Ressource zurück. Da oft der Inhalt des Datenstroms interessant ist, liefert getResourceAsStream() einen InputStream. Intern wird aber nichts anderes gemacht, als getResource() aufgerufen und mit openStream() ein Eingabe-Objekt geholt. Nur getResourceAsStream() fängt eine eventuelle IOException ab und liefert dann die Rückgabe null.

Da der Klassenlader die Ressource findet, entdeckt er alle Dateien, die im Pfad des Klassenladers eingetragen sind. Das gilt auch für Jar-Archive, weil dort vom Klassenlader alles verfügbar ist. Falls die Quelle nicht aufgelöst werden konnte, liefern die Methoden null. null wird auch zurückgegeben, wenn die Sicherheitsrichtlinien das Lesen verbieten.


Beispiel    Besorge einen Eingabestrom in1 auf die Datei kullin_fun.txt und einen zweiten Eingabestrom in2 auf die Datei hirse_fun.jpg innerhalb der Objektmethode lade().

class C
{
  InputStream in1 = C.class.getResourceAsStream( "kullin_fun.txt" );
  void lade()
  {
    InputStream in2 = getClass().getResourceAsStream( "hirse_fun.jpg" );
  }
}

Da zum Nutzen der getResourceXXX()-Methoden ein Class-Objekt nötig ist, zeigt das Beispiel zum einen, dass über C.class das Class-Objekt zu bekommen ist, und zum anderen, dass in einer Objektmethode ebenfalls die geerbte Object-Methode getClass() ein Class-Objekt liefert.


Galileo Computing

12.4.7 Anwenden der Klasse FileInputStream  downtop

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.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Um ein Objekt anzulegen, haben wir die Auswahl zwischen drei Konstruktoren.


class java.io.  FileInputStream
  extends InputStream

gp  FileInputStream( String name ) throws FileNotFoundException Erzeugt einen FileInputStream mit einem gegebenen Dateinamen. Der richtige Dateitrenner, zum Beispiel »\« oder »/«, sollte beachtet werden.
gp  FileInputStream( File file ) throws FileNotFoundException Erzeugt FileInputStream aus einem File-Objekt.
gp  FileInputStream( FileDescriptor fdObj ) Erzeugt FileInputStream aus einem FileDescriptor-Objekt.

Hinweis   Lese den ganzen Dateiinhalt in ein Bytefeld.
File f = new File( dateiname );
byte[] buffer = new byte[ (int) f.length() ];
InputStream in = new FileInputStream( f );
Sinnvoller als das gesamte Einlesen ist aber im Allgemeinen das Lesen in Blöcken.


Galileo Computing

12.4.8 Kopieren von Dateien  downtop

Als Beispiel für das Zusammenspiel von FileInputStream und FileOutputStream wollen wir 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 erledigen wir einfach mit FileOutputStream. Der Methode ist es jedoch relativ gleichgültig, ob es bereits eine Datei dieses Namens 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 gleichnamigen Datei prüfen. 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 dieser Ansatz in Bezug auf die Geschwindigkeit 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 erbringt eine Pufferung über eine Zwischen-Puffer-Klasse keinen Geschwindigkeitsgewinn, da wir ja selbst einen 64 KB-Puffer einrichten.

Listing 12.10   FileCopy.java

import java.io.*;
public class FileCopy
{
  static void copy( InputStream fisOutputStream fos )
  {
    try
    {
      byte[] buffer = new byte[ 0xFFFF ];
      for ( int len; (len = fis.read(buffer)) != –1; )
        fos.write( buffer0len );
    }
    catch( IOException e ) {
      System.err.println( e );
    }
    finally {
      if ( fis != null )
        try { fis.close(); } catch ( IOException e ) { e.printStackTrace(); }
      if ( fos != null )
        try { fos.close(); } catch ( IOException e ) { e.printStackTrace(); }
    }
  }
  static void copyFile( String srcString dest )
  {
    try
    {
      copy( new FileInputStream( src )new FileOutputStream( dest ) );
    }
    catch( IOException e ) {
      e.printStackTrace();
    }
  }
  public static void main( String[] args )
  {
    if ( args.length != 2 )
      System.err.println( "Usage: java FileCopy <src> <dest>" );
    else
      copyFile( args[0]args[1] );
  }
}

Hinweis    Apache Commons IO (http://jakarta.apache.org/commons/io/), bietet über die Klasse IOUtils schon einige fertige copy()-Funktionen.


Galileo Computing

12.4.9 Das FileDescriptor-Objekt  toptop

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 mit keinem 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.

FileOutputStream os = new FileOutputStream(...);
FileDescriptor   fd = os.getFD();
fd.sync();

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.


final class java.io.  FileDeskriptor  

gp  void sync() Materialisiert die Daten. sync() kehrt erst dann zurück, wenn die Daten geschrieben wurden.
 << zurück




Copyright © Galileo Press GmbH 2005
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.


[Galileo Computing]

Galileo Press GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de