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

Inhaltsverzeichnis
Vorwort
1 Java ist auch eine Sprache
2 Sprachbeschreibung
3 Klassen und Objekte
4 Der Umgang mit Zeichenketten
5 Mathematisches
6 Eigene Klassen schreiben
7 Angewandte Objektorientierung
8 Exceptions
9 Die Funktionsbibliothek
10 Threads und nebenläufige Programmierung
11 Raum und Zeit
12 Datenstrukturen und Algorithmen
13 Dateien und Datenströme
14 Die eXtensible Markup Language (XML)
15 Grafische Oberflächen mit Swing
16 Grafikprogrammierung
17 Netzwerkprogrammierung
18 Verteilte Programmierung mit RMI und Web-Services
19 JavaServer Pages und Servlets
20 Applets
21 Midlets und die Java ME
22 Datenbankmanagement mit JDBC
23 Reflection und Annotationen
24 Logging und Monitoring
25 Sicherheitskonzepte
26 Java Native Interface (JNI)
27 Dienstprogramme für die Java-Umgebung
A Die Begleit-DVD
Stichwort

Download:
- ZIP, ca. 12,5 MB
Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Java ist auch eine Insel von Christian Ullenboom
Programmieren mit der Java Standard Edition Version 6
Buch: Java ist auch eine Insel

Java ist auch eine Insel
7., aktualisierte Auflage
geb., mit DVD (November 2007)
1.492 S., 49,90 Euro
Galileo Computing
ISBN 978-3-8362-1146-8
Pfeil 13 Dateien und Datenströme
Pfeil 13.1 Datei und Verzeichnis
Pfeil 13.1.1 Dateien und Verzeichnisse mit der Klasse File
Pfeil 13.1.2 Verzeichnis oder Datei? Existiert es?
Pfeil 13.1.3 Verzeichnis- und Dateieigenschaften/-attribute
Pfeil 13.1.4 Wurzelverzeichnis, Laufwerksnamen, Plattenspeicher
Pfeil 13.1.5 Umbenennen und Verzeichnisse anlegen
Pfeil 13.1.6 Verzeichnisse listen und Dateien filtern
Pfeil 13.1.7 Dateien berühren, neue Dateien anlegen, temporäre Dateien
Pfeil 13.1.8 Dateien und Verzeichnisse löschen
Pfeil 13.1.9 Verzeichnisse nach Dateien iterativ durchsuchen
Pfeil 13.1.10 URL- und URI-Objekte aus einem File-Objekt ableiten
Pfeil 13.1.11 Mit Locking Dateien sperren
Pfeil 13.1.12 Sicherheitsprüfung
Pfeil 13.1.13 Mime-Typen mit dem JavaBeans Activation Framework (JAF)
Pfeil 13.1.14 Zugriff auf SMB-Server mit jCIFS
Pfeil 13.2 Dateien mit wahlfreiem Zugriff
Pfeil 13.2.1 Ein RandomAccessFile zum Lesen und Schreiben öffnen
Pfeil 13.2.2 Aus dem RandomAccessFile lesen
Pfeil 13.2.3 Schreiben mit RandomAccessFile
Pfeil 13.2.4 Die Länge des RandomAccessFile
Pfeil 13.2.5 Hin und her in der Datei
Pfeil 13.2.6 Wahlfreier Zugriff und Pufferung mit Unified I/O
Pfeil 13.3 Stream-Klassen und Reader/Writer am Beispiel von Dateien
Pfeil 13.3.1 Mit dem FileWriter Texte in Dateien schreiben
Pfeil 13.3.2 Zeichen mit der Klasse FileReader lesen
Pfeil 13.3.3 Kopieren mit FileOutputStream und FileInputStream
Pfeil 13.3.4 Das FileDescriptor-Objekt
Pfeil 13.4 Basisklassen für die Ein-/Ausgabe
Pfeil 13.4.1 Die abstrakten Basisklassen
Pfeil 13.4.2 Übersicht über Ein-/Ausgabeklassen
Pfeil 13.4.3 Die abstrakte Basisklasse OutputStream
Pfeil 13.4.4 Die Schnittstellen Closeable und Flushable
Pfeil 13.4.5 Ein Datenschlucker
Pfeil 13.4.6 Die abstrakte Basisklasse InputStream
Pfeil 13.4.7 Ressourcen wie Grafiken aus dem Klassenpfad und aus Jar–Archiven laden
Pfeil 13.4.8 Ströme mit SequenceInputStream zusammensetzen
Pfeil 13.4.9 Die abstrakte Basisklasse Writer
Pfeil 13.4.10 Die Schnittstelle Appendable
Pfeil 13.4.11 Die abstrakte Basisklasse Reader
Pfeil 13.5 Formatierte Textausgaben
Pfeil 13.5.1 Die Klassen PrintWriter und PrintStream
Pfeil 13.5.2 System.out, System.err und System.in
Pfeil 13.5.3 Geschützte Passwort-Eingaben mit der Klasse Console
Pfeil 13.6 Schreiben und Lesen aus Strings und Byte-Feldern
Pfeil 13.6.1 Mit dem StringWriter ein String-Objekt füllen
Pfeil 13.6.2 CharArrayWriter
Pfeil 13.6.3 StringReader und CharArrayReader
Pfeil 13.6.4 Mit ByteArrayOutputStream in ein Byte-Feld schreiben
Pfeil 13.6.5 Mit ByteArrayInputStream aus einem Byte-Feld lesen
Pfeil 13.7 Datenströme filtern und verketten
Pfeil 13.7.1 Streams als Filter verketten
Pfeil 13.7.2 Gepufferte Ausgaben mit BufferedWriter und BufferedOutputStream
Pfeil 13.7.3 Gepufferte Eingaben mit BufferedReader und BufferedInputStream
Pfeil 13.7.4 LineNumberReader zählt automatisch Zeilen mit
Pfeil 13.7.5 Daten mit der Klasse PushbackReader zurücklegen
Pfeil 13.7.6 DataOutputStream/DataInputStream
Pfeil 13.7.7 Basisklassen für Filter
Pfeil 13.7.8 Die Basisklasse FilterWriter
Pfeil 13.7.9 Ein LowerCaseWriter
Pfeil 13.7.10 Eingaben mit der Klasse FilterReader filtern
Pfeil 13.8 Vermittler zwischen Byte-Streams und Unicode-Strömen
Pfeil 13.8.1 Datenkonvertierung durch den OutputStreamWriter
Pfeil 13.8.2 Automatische Konvertierungen mit dem InputStreamReader
Pfeil 13.9 Kommunikation zwischen Threads mit Pipes
Pfeil 13.9.1 PipedOutputStream und PipedInputStream
Pfeil 13.9.2 PipedWriter und PipedReader
Pfeil 13.10 Datenkompression
Pfeil 13.10.1 Java-Unterstützung beim Komprimieren und Zusammenpacken
Pfeil 13.10.2 Datenströme komprimieren
Pfeil 13.10.3 Zip-Archive
Pfeil 13.10.4 Jar-Archive
Pfeil 13.11 Prüfsummen
Pfeil 13.11.1 Die Schnittstelle Checksum
Pfeil 13.11.2 Die Klasse CRC32
Pfeil 13.11.3 Die Adler32-Klasse
Pfeil 13.12 Persistente Objekte und Serialisierung
Pfeil 13.12.1 Objekte mit der Standard-Serialisierung speichern und lesen
Pfeil 13.12.2 Zwei einfache Anwendungen der Serialisierung
Pfeil 13.12.3 Die Schnittstelle Serializable
Pfeil 13.12.4 Nicht serialisierbare Attribute aussparen
Pfeil 13.12.5 Das Abspeichern selbst in die Hand nehmen
Pfeil 13.12.6 Tiefe Objektkopien
Pfeil 13.12.7 Versionenverwaltung und die SUID
Pfeil 13.12.8 Wie die ArrayList serialisiert
Pfeil 13.12.9 Probleme mit der Serialisierung
Pfeil 13.12.10 Serialisieren in XML-Dateien
Pfeil 13.12.11 JavaBeans Persistence
Pfeil 13.12.12 XStream
Pfeil 13.13 Tokenizer
Pfeil 13.13.1 StreamTokenizer
Pfeil 13.13.2 CSV-(Comma Separated Values-)Dateien verarbeiten
Pfeil 13.14 Zum Weiterlesen

Schlagfertigkeit ist jede Antwort, die so klug ist, dass der Zuhörer wünscht, er hätte sie gegeben. – Elbert Hubbard

13 Dateien und Datenströme

Computer sind für uns so nützlich, weil sie Daten bearbeiten. Der Bearbeitungszyklus beginnt mit dem Einlesen der Daten, umfasst das Verarbeiten und endet mit der Datenausgabe. In der deutschsprachigen Informatikliteratur wird deswegen auch vom EVA [EVA ist ein Akronym für »Eingabe, Verarbeitung, Ausgabe«. Diese Reihenfolge entspricht dem Arbeitsweg. Zunächst werden die Eingaben von einem Eingabegerät gelesen, dann durch den Computer verarbeitet und anschließend ausgegeben (in welcher Form auch immer). ] -Prinzip der Datenverarbeitungsanlagen gesprochen. In frühen EDV-Zeiten wurde die Eingabe vom Systemoperator auf Lochkarten gestanzt. Glücklicherweise sind diese Zeiten vorbei. Heutzutage speichern wir unsere Daten in Dateien (engl. files [Das englische Wort »file« geht auf das lateinische Wort »filum« zurück. Dies bezeichnete früher eine auf Draht aufgereihte Sammlung von Schriftstücken. ] ) und Datenbanken ab. Es ist wichtig zu bemerken, dass eine Datei nur in ihrem Kontext interessant ist, andernfalls beinhaltet sie für uns keine Information – die Sichtweise auf eine Datei ist demnach wichtig. Auch ein Programm besteht aus Daten und wird oft in Form einer Datei repräsentiert.

Um an die Information einer Datei zu gelangen, müssen wir den Inhalt auslesen können. Zudem müssen wir in der Lage sein, Dateien anzulegen, zu löschen, umzubenennen und sie in Verzeichnissen zu strukturieren. Java bietet uns eine Vielzahl von Zugriffsmöglichkeiten auf Dateien. Ein wichtiges Schlagwort in diesem Zusammenhang ist der Datenstrom (engl. stream). Dieser entsteht beim Fluss der Daten von der Eingabe über die Verarbeitung hin zur Ausgabe. Mittels Datenströmen können Daten sehr elegant bewegt werden; ein Programm ohne Datenfluss ist eigentlich undenkbar. Die Eingabeströme (engl. input streams) sind zum Beispiel Daten der Tastatur oder vom Netzwerk; über die Ausgabeströme (engl. output streams) fließen die Daten in ein Ausgabemedium, beispielsweise in den Drucker oder in eine Datei. Die Kommunikation der Threads erfolgt über Pipes.

In Java sind über dreißig Klassen zur Verarbeitung der Datenströme vorgesehen. Da die Datenströme an kein spezielles Ein- oder Ausgabeobjekt gebunden sind, können sie beliebig miteinander gemischt werden. Dies ist mit dem elektrischen Strom vergleichbar. Es gibt mehrere Stromlieferanten (Solarkraftwerke, Nutzung geothermischer Energie, Umwandlung von Meereswärmeenergie (OTEC)) und mehrere Verbraucher (Wärmedecke, Mikrowelle), die die Energie wieder umsetzen.


Galileo Computing - Zum Seitenanfang

13.1 Datei und Verzeichnis Zur nächsten ÜberschriftZur vorigen Überschrift

Da durch Datenströme keine Dateien gelöscht oder umbenannt werden können, liefert uns ein File-Objekt Informationen über Dateien und Verzeichnisse. Dieses Objekt wurde eingeführt, um Dateioperationen plattformunabhängig durchzuführen, was aber leider auch eine Einschränkung darstellt, denn wie sollen Rechte vergeben werden, wenn dies etwa der Macintosh mit Mac OS 9 oder ein Palm-Pilot nicht unterstützen? Auch Unix und Windows haben zwei völlig verschiedene Ansätze zur Rechteverwaltung.


Galileo Computing - Zum Seitenanfang

13.1.1 Dateien und Verzeichnisse mit der Klasse File Zur nächsten ÜberschriftZur vorigen Überschrift

Ein konkretes File-Objekt repräsentiert einen Datei- oder Verzeichnisnamen im Dateisystem. Der Verweis wird durch einen Pfadnamen spezifiziert. Dieser kann absolut oder relativ zum aktuellen Verzeichnis angegeben werden.


Beispiel Beispiel Erzeuge ein File-Objekt für das Laufwerk »C:/«:

File f = new File( "C:/" ); 
System.out.println( f );   // C:\

Folgende Konstruktoren erzeugen ein File-Objekt:


class java.io.File 
implements Serializable, Comparable<File>

  • File( String pathname ) Erzeugt ein File-Objekt aus einem Dateinamen.
  • File( String parent, String child )
  • File( File parent, String child ) Setzt ein neues File-Objekt aus einem Basisverzeichnis und einem weiteren Teil zusammen, der auch wieder ein Verzeichnis oder ein Dateiname sein kann.
  • File( URI uri ) Fragt von uri den Pfadnamen (uri.getPath()) und erzeugt ein neues File-Objekt. Ist uri gleich null, folgt eine NullPointerException. Ist die URI falsch formuliert, gibt es eine IllegalArgumentException.

Die Pfadangabe kann in allen Fällen absolut sein, muss es aber nicht.

Pfadtrenner

Die Angabe des Pfades ist wegen der Pfadtrenner plattformabhängig. Auf Windows-Rechnern trennt ein Backslash »\« die Pfade, auf Unix-Maschinen ein normaler Slash »/« – auch Divis genannt –, und und unter dem älteren MAC OS 9 ein Doppelpunkt.

Glücklicherweise speichert die Klasse File den Pfadtrenner in zwei öffentlichen Konstanten: File.separatorChar [Eigentlich sollte der Variablenname großgeschrieben werden, da die Variable als public static final char eine Konstante ist. ] ist ein char, und File.separator stellt den Pfadtrenner als String bereit. (Dies ist wiederum auf System.getProperty("file.separator") zurückzuführen.)


Hinweis Hinweis Wie bei den Dateitrennern gibt es einen Unterschied bei der Darstellung des Wurzelverzeichnisses. Unter Unix ist dies ein einzelnes Divis »/«, und unter Windows steht die Laufwerksbezeichnung vor dem Doppelpunkt und dem Backslash-Zeichen (»Z:\«).


Abbildung 13.1 Namen erfragen und auflösen

Mit einem File-Objekt erfragen ganz unterschiedliche Methoden den Dateinamen, den kompletten Pfad, das vorangehende Verzeichnis und ob eine Angabe absolut oder relativ ist.


Beispiel Beispiel Liefere einen Dateinamen, bei dem die relativen Bezüge aufgelöst sind:

try 
{ 
  File file = new File("C:/./WasNDas//..\\Programme/").getCanonicalFile(); 
  System.out.println( file );                          // C:\Programme 
} 
catch ( IOException e ) { e.printStackTrace(); }


class java.io.File 
implements Serializable, Comparable<File>

  • String getAbsolutePath() Liefert den absoluten Pfad. Ist das Objekt kein absoluter Pfadname, so wird ein String aus aktuellem Verzeichnis, Separator-Zeichen und Dateinamen des Objekts verknüpft.
  • String getCanonicalPath() throws IOException
  • File getCanonicalFile() throws IOException Gibt den Pfadnamen des Dateiobjekts zurück, der keine relativen Pfadangaben mehr enthält. Kann im Gegensatz zu den anderen Pfadfunktionen eine IOException aufrufen, da mitunter verbotene Dateizugriffe erfolgen.
  • String getName() Gibt den Dateinamen zurück.
  • String getParent() Gibt den Pfadnamen des Vorgängers zurück.
  • String getPath() Gibt den Pfadnamen zurück.
  • boolean isAbsolute() true, wenn der Pfad in der systemabhängigen Notation absolut ist.

Beispiel Beispiel Um festzustellen, ob f das Wurzelverzeichnis ist, genügt die folgende Zeile:

if ( f.getPath().equals(f.getParent()) ) 
 // File f ist root


Galileo Computing - Zum Seitenanfang

13.1.2 Verzeichnis oder Datei? Existiert es? Zur nächsten ÜberschriftZur vorigen Überschrift

Das File-Objekt muss nicht unbedingt eine existierende Datei oder ein existierendes Verzeichnis repräsentieren. Für Dateioperationen mit File-Objekten und nachfolgendem Zugriff testet exists(), ob die Datei oder das Verzeichnis tatsächlich vorhanden ist. Da nun aber ein File-Objekt Dateien sowie Verzeichnisse gleichzeitig repräsentiert, ermöglichen isDirectory() und isFile() eine genauere Aussage über den File-Typ. Es kann gut sein, dass für eine File weder isDirectory() noch isFile() die Rückgabe true liefern. (In Java können nur normale Dateien erzeugt werden.)


class java.io.File 
implements Serializable, Comparable<File>

  • boolean exists() Liefert true, wenn das File-Objekt eine existierende Datei oder einen existierenden Ordner repräsentiert.
  • boolean isDirectory() Gibt true zurück, wenn es sich um ein Verzeichnis handelt.
  • boolean isFile() true, wenn es sich um eine »normale« Datei handelt (kein Verzeichnis und keine Datei, die vom zugrunde liegenden Betriebssystem als besonders markiert wird; Blockdateien, Links unter Unix).

Galileo Computing - Zum Seitenanfang

13.1.3 Verzeichnis- und Dateieigenschaften/-attribute Zur nächsten ÜberschriftZur vorigen Überschrift

Eine Datei oder ein Verzeichnis besitzt zahlreiche Eigenschaften, die sich mit Anfragemethoden auslesen lassen. In einigen wenigen Fällen lassen sich die Attribute auch ändern.


class java.io.File 
implements Serializable, Comparable<File>

  • boolean canExecute(), canRead(), canWrite() true, wenn die Ausführungsrechte/Leserechte/Schreibrechte gesetzt sind.
  • long length() Gibt die Länge der Datei in Byte zurück oder 0L, wenn die Datei nicht existiert oder es sich um ein Verzeichnis handelt.

Änderungsdatum einer Datei

Eine Datei verfügt unter jedem Dateisystem nicht nur über Attribute wie Größe und Rechte, sondern verwaltet auch das Datum der letzten Änderung. Letzteres nennt sich Zeitstempel. Die File-Klasse verfügt zum Abfragen dieser Zeit über die Methode lastModified() und zum Setzen über setLastModified().

Die Methode setLastModified() ändert – wenn möglich – den Zeitstempel, und ein anschließender Aufruf von lastModified() liefert die gesetzte Zeit – womöglich gerundet – zurück. Die Funktion ist von vielfachem Nutzen, aber sicherheitsbedenklich, denn ein Programm kann den Dateiinhalt einschließlich des Zeitstempels ändern. Auf den ersten Blick ist nicht mehr erkennbar, dass eine Veränderung der Datei vorgenommen wurde. Doch die Funktion ist von größerem Nutzen bei der Programmerstellung, wo Quellcodedateien etwa mit Objektdateien verbunden sind. Nur über einen Zeitstempel ist eine einigermaßen intelligente Projektdateiverwaltung möglich.

Dabei bleibt es verwunderlich, warum lastModified() nicht als veraltet ausgezeichnet ist und zu getLastModified() wurde, wo doch nun die passende Funktion zum Setzen der Namensgebung genügt.


class java.io.File 
implements Serializable, Comparable<File>

  • long lastModified() Liefert den Zeitpunkt, zu dem die Datei zum letzten Mal geändert wurde. Die Zeit wird in Millisekunden ab dem 1. Januar 1970, 00:00:00 UTC, gemessen. Die Methode liefert 0, wenn die Datei nicht existiert oder ein Ein-/Ausgabefehler auftritt.
  • boolean setLastModified( long time ) Setzt die Zeit (wann die Datei zuletzt geändert wurde). Die Zeit ist wiederum in Millisekunden seit dem 1. Januar 1970 angegeben. Ist das Argument negativ, dann wird eine IllegalArgumentException ausgelöst.

Hinweis Hinweis Zwar lässt Java die Ermittlung der Zeit der letzten Änderung zu, doch gilt dies nicht für die Erzeugungszeit. Das Standard-Dateisystem von Unix-Systemen speichert diese Zeit nicht. Windows speichert sie hingegen schon, sodass hier grundsätzlich der Zugriff, etwa über JNI, möglich wäre. Legt ein Java-Programm die Dateien an, deren Anlegezeiten später wichtig sind, müssen die Zeiten beim Anlegen gemessen und gespeichert werden. Falls die Datei nicht verändert wird, stimmt lastModified() mit der Anlegezeit überein.


Dateiattribute verändern

Zu den Anfragemethoden canXXX() kann ein File-Objekt auch Dateiattribute verändern, wobei viele Methoden seit Java 6 neu sind.


Beispiel Beispiel Lege eine neue temporäre Datei an, und teste das Lesen und Verändern des Lese-Schreib-Attributs. Nach dem Test lösche die Datei wieder:

Listing 13.1 com/tutego/insel/io/file/PermissionDemo.java, main()

File f = File.createTempFile( "bla", "blub" ); 
System.out.printf( "readable=%s, writable=%s%n", f.canRead(), f.canWrite() ); 
f.setReadOnly(); 
System.out.printf( "readable=%s, writable=%s%n", f.canRead(), f.canWrite() ); 
f.setWritable( true ); 
System.out.printf( "readable=%s, writable=%s%n", f.canRead(), f.canWrite() ); 
f.deleteOnExit();

Die Ausgabe ist:

readable=true, writable=true 
readable=true, writable=false 
readable=true, writable=true

Es gibt Funktionen wie setLastModified(), die auf dem Datei-Objekt wirklich eine Änderung ausführen. Insofern muss die Aussage von Sun in der API-Dokumentation genau genommen werden: »Instances of the File class are immutable; that is, once created, the abstract pathname represented by a File object will never change.« Nur der Dateiname ist immutable, aber nicht die Zustände.


class java.io.File 
implements Serializable, Comparable<File>

  • boolean setReadOnly() Setzt die Datei auf nur-lesend. Liefert »wahr«, wenn die Änderung möglich war.
  • boolean setExecutable( boolean executable, boolean ownerOnly )
  • boolean setReadable( boolean readable, boolean ownerOnly )
  • boolean setWritable( boolean writable, boolean ownerOnly ) Setzt das Recht zum Ausführen/Lesen/Schreiben der Datei. Ist ownerOnly true, gilt das Recht nur für den Benutzer, sonst für alle.
  • boolean setExecutable( boolean executable )
  • boolean setReadable( boolean readable )
  • boolean setWritable( boolean writable ) Leitet weiter an die mit zwei Parametern definierten Methoden setXXXable(boolean, boolean), und das zweite Argument ist true.

Ist eine Datei eine Verknüpfung?

Bisher ist die File-Klasse noch nicht so ausgestattet, dass sie alle Fragen ohne Hacks beantwortet. Mit der JSR 203: »More New I/O APIs for the Java Platform« ist hoffentlich Besserung auf dem Weg, aber heute kann die Frage nach der Dateiverknüpfung nur eine interne sun.awt.shell.ShellFolder beantworten. Die Klasse liefert bei .lnk-Dateien unter Windows mit isLink() ein klares true/false, gibt die Zieladresse mit getLinkLocation() und auf Anfrage mit getIcon() das assoziierte Datei-Icon als Image dazu.

Listing 13.2 ShellFolderDemo.java, main()

String s =  
"C:\\Dokumente und Einstellungen\\All Users\\Startmenü\\Programmzugriff und  
-standards.lnk"; 
ShellFolder folder = ShellFolder.getShellFolder( new File( s ) ); 
System.out.println( folder.getFolderType() );     // Verknüpfung 
if ( folder.isLink() ) 
  System.out.println( folder.getLinkLocation() ); // C:\WINDOWS\system32\control.exe

Galileo Computing - Zum Seitenanfang

13.1.4 Wurzelverzeichnis, Laufwerksnamen, Plattenspeicher Zur nächsten ÜberschriftZur vorigen Überschrift

Die statische Funktion listRoots() gibt ein Feld von File-Objekten zurück. Jeder Eintrag des Feldes repräsentiert ein Wurzel (engl. root) des Dateisystems. Dies macht es einfach, Programme zu schreiben, die etwa über dem Dateisystem eine Suche ausführen. Da es unter Unix nur eine Wurzel gibt, ist der Rückgabewert von File.listRoots() immer »/« – ein anderes Root gibt es nicht. Unter Windows wird es aber zu einem richtigen Feld, da es mehrere Wurzeln für die Partitionen oder logischen Laufwerke gibt. Die Wurzeln tragen Namen wie »A:« oder »Z:«. Dynamisch eingebundene Laufwerke, die etwa unter Unix mit »mount« integriert werden, oder Wechselfestplatten werden mit berücksichtigt. Die Liste wird immer dann aufgebaut, wenn listRoots() aufgerufen wird. Komplizierter ist es, wenn entfernte Dateibäume mittels NFS oder SMB eingebunden sind, weil es dann nicht darauf ankommt, ob das zuständige Programm eine Verbindung noch aktiv hält oder nicht. Denn nach einer abgelaufenen Zeit ohne Zugriff wird das Verzeichnis wieder aus der Liste genommen. Dies ist aber wieder sehr plattformabhängig.


Beispiel Beispiel Gewünscht ist eine Liste der verfügbaren Wurzeln mit der Angabe, ob auf das Gerät eine Zugriffsmöglichkeit besteht. Ist unter Windows etwa ein Diskettenlaufwerk eingebunden, befindet sich aber keine Diskette im Schacht, dann ist das Gerät nicht bereit. Ein Diskettenlaufwerk taucht in der Liste auf, aber exists() liefert false.

Listing 13.3 com/tutego/insel/io/file/ListRoot.java. main()

for ( File root : File.listRoots() ) 
  System.out.println( root.getPath() + " ist " + 
                      (root.exists() ? "" : "nicht ") + "bereit" );

Bei der Ausgabe mit System.out.println() entspricht root.getPath() einem root.to-String(). Da aber nicht unbedingt klar ist, dass toString() auf getPath() verweist, schreiben wir getPath() direkt.



class java.io.File 
implements Serializable, Comparable<File>

  • static File[] listRoots() Liefert die verfügbaren Wurzeln der Dateisysteme oder null, falls diese nicht festgestellt werden können. Jedes File-Objekt beschreibt eine Dateiwurzel. Es ist gewährleistet, dass alle kanonischen Pfadnamen mit einer der Wurzeln beginnen. Wurzeln, für die der SecurityManager den Zugriff verweigert, werden nicht aufgeführt. Das Feld ist leer, falls es keine Dateisystem-Wurzeln gibt.

Namen der Laufwerke

Die Namen der Laufwerksbuchstaben sind ein wenig versteckt, denn eine Methode zum Erfragen ist nicht bei der Klasse File zu finden. Zwar liefert listRoots() schon einen passenden Anfang, um unter Windows die Laufwerke preiszugeben, aber die Namen liefert erst getSystemDisplayName() des FileSystemView-Objekts. Die Klasse gehört zu Swing und dort zum Dateiauswahldialog.


Beispiel Beispiele Zeige alle Laufwerksbuchstaben:

Listing 13.4 com/tutego/insel/io/file/SystemDisplayName.java. main()

FileSystemView view = FileSystemView.getFileSystemView(); 
for ( File f : File.listRoots() ) 
  System.out.println( view.getSystemDisplayName(f) );

Die Ausgabe ist bei mir:

WINDOWS (C:) 
Daten (D:) 
Share (S:)


abstract class javax.swing.filechooser.FileSystemView

  • static FileSystemView getFileSystemView() Fabrikfunktion, die ein Exemplar von FileSystemView liefert.
  • boolean isDrive( File dir )
  • boolean isFloppyDrive( File dir )
  • boolean isComputerNode( File dir ) Ist dir ein Laufwerk/Wechsellaufwerk/Netzwerk-Knoten?

FileSystemView hält noch andere gute Funktionen bereit, wie getHomeDirectory() oder isTraversable(File f).

Freier Plattenspeicher

In Java 6 sind die Methoden getFreeSpace(), getUsableSpace() und getTotalSpace() zum Ermitteln des freien Plattenspeichers hinzugekommen.

Listing 13.5 com/tutego/insel/io/file/DiscSpace.java. main()

System.out.println( "Drive    Total       Free    Usable" ); 
System.out.println( "-----------------------------------" ); 
 
for ( File dir : File.listRoots() ) 
  System.out.printf( "%s   %5d MB   %5d MB  %5d MB%n", dir, 
                     dir.getTotalSpace() / (1024*1024), 
                     dir.getFreeSpace() / (1024*1024), 
                     dir.getUsableSpace() / (1024*1024) );

Die Ausgabe ist bei mir:

Drive    Total       Free    Usable 
----------------------------------- 
C:\   10001 MB    1467 MB   1467 MB 
D:\   66283 MB   63477 MB  63477 MB 
S:\   32145 MB    3194 MB   3194 MB

Galileo Computing - Zum Seitenanfang

13.1.5 Umbenennen und Verzeichnisse anlegen Zur nächsten ÜberschriftZur vorigen Überschrift

Mit mkdir() lassen sich Verzeichnisse anlegen und mit renameTo() Dateien oder Verzeichnisse umbenennen.


class java.io.File 
implements Serializable, Comparable<File>

  • boolean mkdir() Legt das Unterverzeichnis an.
  • boolean mkdirs() Legt das Unterverzeichnis inklusive weiterer Verzeichnisse an.
  • boolean renameTo( File d ) Benennt die Datei in den Namen um, der durch das File-Objekt d gegeben ist. Ging alles gut, wird true zurückgegeben. Bei zwei Dateinamen alt und neu benennt new File(alt).renameTo(new File(neu)); die Datei um. Die Methode muss nicht atomar ausgeführt werden, und die tatsächliche Implementierung ist von der JVM und vom Betriebssystem abhängig.

Über renameTo() sollte noch ein Wort verloren werden: File-Objekte sind immutable, stehen also immer nur für genau eine Datei. Ändert sich der Dateiname, ist das File-Objekt ungültig und es ist kein Zugriff mehr über dieses File-Objekt erlaubt. Auch wenn eine Laufzeitumgebung keine Exception auslöst, sind alle folgenden Ergebnisse von Anfragen unsinnig.

Zum Teil kann renameTo() auch zum Verschieben von Dateien dienen. Oft gilt aber die Einschränkung, dass dies nur auf demselben Datenträger möglich ist (also etwa von Laufwerk C nach C:/, aber nicht von C nach D:/), Links und sonstige Dateivarianten nicht eingerechnet.


Galileo Computing - Zum Seitenanfang

13.1.6 Verzeichnisse listen und Dateien filtern Zur nächsten ÜberschriftZur vorigen Überschrift

Um eine Verzeichnisanzeige oder einen Dateiauswahldialog zu programmieren, benötigen wir eine Liste von Dateien, die in einem Verzeichnis liegen. Ein Verzeichnis kann reine Dateien oder auch wieder Unterverzeichnisse besitzen. Die list()- und listFiles()-Funktionen der Klasse File geben ein Feld von Zeichenketten mit Dateien und Verzeichnissen beziehungsweise ein Feld von File-Objekten mit den beinhalteten Elementen zurück.


class java.io.File 
implements Serializable, Comparable<File>

  • File[] listFiles()
  • String[] list() Gibt eine Liste der Dateien in einem Verzeichnis als File-Array oder String-Array zurück. Das Feld enthält weder ».« noch »..«.

Beispiel Beispiel Ein einfacher Directory-Befehl ist leicht mittels einiger Zeilen programmiert:

String[] entries = new File( "." ).list(); 
System.out.println( Arrays.toString(entries) );

Die einfache Funktion list() liefert dabei nur relative Pfade, also einfach den Dateinamen oder den Verzeichnisnamen. Den absoluten Namen zu einer Dateiquelle müssen wir also erst zusammensetzen. Praktischer ist da schon die Methode listFiles(), da wir hier komplette File-Objekte bekommen, die ihre ganze Pfadangabe schon kennen. Wir können den Pfad mit getName() erfragen.

Dateien mit FilenameFilter und FileFilter nach Kriterien filtern

Ein Filter filtert aus den Dateinamen diejenigen heraus, die einem gesetzten Kriterium genügen. Eine Möglichkeit ist, nach den Endungen zu separieren. Doch auch komplexere Selektionen sind denkbar; so kann in die Datei hineingesehen werden, ob sie beispielsweise bestimmte Informationen am Dateianfang enthält. Besonders für Macintosh-Benutzer ist dies wichtig zu wissen, denn dort sind die Dateien nicht nach Endungen sortiert. Die Information liegt in den Dateien selbst. Windows versucht uns auch diese Dateitypen vorzuenthalten, von dieser Kennung hängt jedoch alles ab. Wer die Endung einer Grafikdatei schon einmal umbenannt hat, der weiß, warum Grafikprogramme aufgerufen werden. Von den Endungen hängt also sehr viel ab.

Sollen aus einer Liste von Dateien einige mit besonderen Eigenschaften herausgenommen werden, so müssen wir dies nicht selbst programmieren. Schlüssel hierzu ist die Schnittstelle FilenameFilter und FileFilter. Wenn wir etwas später den grafischen Dateiauswahldialog kennenlernen, so können wir dort auch den FilenameFilter einsetzen. [Leider hatte der Fehlerteufel seine Finger im Spiel, und der FilenameFilter funktioniert nicht, weil der FileSelector fehlerhaft ist. Obwohl die Funktionalität dokumentiert ist, findet sich unter der Bug-Nummer 4031440 kurz: »The main issue is that support for FilenameFilter in the FileDialog class was never implemented on any platform – it’s not that there’s a bug which needs to be fixed, but that there’s no code to run nor was the design ever evaluated to see if it *could* be implemented on our target platforms.« ] Eine Filter-Klasse implementiert die Funktion accept() so, dass alle von accept() angenommenen Dateien den Rückgabewert true liefern.


interface java.io.FileFilter

  • boolean accept( File pathname ) Muss true liefern, wenn die Datei pathname in die Ergebnisliste aufgenommen werden soll.

interface java.io.FilenameFilter

  • boolean accept( File dir, String name ) Muss true liefern, wenn die Datei mit dem Namennamen name im Verzeichnis dir in die Ergebnisliste soll.

Beim FilenameFilter empfängt accept() zwei Argumente, nämlich das Verzeichnis dir, in dem die Datei name liegt; und beim FileFilter enthält pathname die voll qualifiziert Datei schon direkt als File-Objekt. (Was für Dateien in einem Verzeichnis gilt, gilt ebenso für Unterverzeichnisse.) Im Fall von FileFilter liefert also pathname.getName() den Dateinamen.


Beispiel Beispiel Wollen wir nur auf Textdateien reagieren, so geben wir ein true bei allen Dateien mit der Endung .txt zurück. Die anderen werden mit false abgelehnt.

Listing 13.6 com/tutego/insel/io/file/TxtFilenameFilter.java, TxtFilenameFilter

public class TxtFilenameFilter implements FilenameFilter { 
  public boolean accept( File f, String s ) { 
    return new File(f, s).isFile() && 
           s.toLowerCase().endsWith( ".txt" ); 
  } 
}

Exemplare der implementierenden Klassen werden der Methode list() bzw. listFiles() als Argument übergeben.


class java.io.File 
implements Serializable, Comparable<File>

  • String[] list( FilenameFilter filter ) Wie list(), nur filtert ein spezielles FilenameFilter-Objekt Objekte heraus.
  • File[] listFiles( FilenameFilter filter ) Wie listFiles(), nur filtert ein spezielles FilenameFilter-Objekt Objekte heraus.
  • File[] listFiles( FileFilter filter ) Wie list(), nur filtert ein spezielles FileFilter-Objekt bestimmte Objekte heraus.

Nun kann list() mit dem FilenameFilter und listFiles() mit dem FileFilter bzw. FilenameFilter aufgerufen werden. Die Methode erfragt zuerst alle Dateien und Unterverzeichnisse und ruft dann für jeden Eintrag die accept()-Methode auf. Bei der Rückgabe true nimmt die Auflist-Methode den Eintrag in eine interne Liste auf, die dann später als Feld zurückgegeben wird.


Beispiel Beispiel Zur Implementierung von FilenameFilter und FileFilter bieten sich innere Klassen an. In einem Beispiel soll listFiles() nur Unterverzeichnisse von dir zurückliefern:

Listing 13.7 com/tutego/insel/io/file/SubDir.java, main() Ausschnitt

File[] subDirs = dir.listFiles( new FileFilter() { 
  public boolean accept( File d ) { 
    return d.isDirectory(); 
  } } );

Dateien aus dem aktuellen Verzeichnis filtern

Wir können somit ein einfaches Verzeichnisprogramm programmieren, indem wir die Funktionen von getProperty() und list() zusammenfügen. Zusätzlich wollen wir nur Dateien mit der Endung .txt angezeigt bekommen.

Listing 13.8 com/tutego/insel/io/file/Dir.java

package com.tutego.insel.io.file; 
 
import java.io.*; 
 
public class Dir 
{ 
  public static void main( String[] args ) 
  { 
    File userdir = new File( System.getProperty("user.dir") ); 
    System.out.println( userdir ); 
 
    for ( File file : userdir.listFiles(new TxtFilenameFilter()) ) 
      System.out.println( file ); 
  } 
}

Hinweis Hinweis Die zusätzliche Java-Bibliothek Apache Commons IO (http://jakarta.apache.org/commons/io/) bietet über das Paket org.apache.commons.io.filefilter vielfältige Datei-Filter, wie SuffixFileFilter oder WildcardFilter.



Galileo Computing - Zum Seitenanfang

13.1.7 Dateien berühren, neue Dateien anlegen, temporäre Dateien Zur nächsten ÜberschriftZur vorigen Überschrift

Unter dem Unix-System gibt es das Shell-Kommando touch, das wir in einer einfachen Variante in Java umsetzen wollen. Das Programm berührt (engl. touch) eine Datei, indem der Zeitstempel auf das aktuelle Datum gesetzt wird. Wie beim Kommando touch soll unser Java-Programm über alle auf der Kommandozeile übergebenen Dateien gehen und sie berühren. Falls eine Datei nicht existiert, soll sie kurzerhand angelegt werden.

Listing 13.9 com/tutego/insel/io/file/Touch.java

package com.tutego.insel.io.file; 
 
import java.io.*; 
 
public class Touch 
{ 
  public static void main( String[] args ) 
  { 
    for ( String s : args ) 
    { 
      File f = new File( s ); 
 
      if ( f.exists() ) 
      { 
        if ( f.setLastModified( System.currentTimeMillis() ) ) 
          System.out.println( "touched " + s ); 
        else 
          System.out.println( "touch failed on " + s ); 
      } 
      else 
      { 
        try 
        { 
          f.createNewFile(); 
          System.out.println( "create new file " + s ); 
        } catch ( IOException e ) { e.printStackTrace(); } 
      } 
    } 
  } 
}

Gibt setLastModified() den Wahrheitswert false zurück, so wissen wir, dass die Operation fehlschlug, und geben eine Informationsmeldung aus.


class java.io.File 
implements Serializable, Comparable<File>

  • boolean createNewFile() throws IOException Legt atomar eine neue, leere Datei mit dem im File-Objekt gespeicherten Namen an, wenn eine Datei mit diesem Namen noch nicht existiert.
  • static File createTempFile( String prefix, String suffix ) throws IOException Legt eine neue Datei im temporären Verzeichnis an. Das Verzeichnis ist häufig unter einem Standard-Unix /tmp oder unter Windows C:\Dokumente und Einstellungen\Benutzername\Lokale Einstellungen\Temp. Der Dateiname setzt sich aus einem benutzerdefinierten Präfix, einer Zufallsfolge und einem Suffix zusammen.
  • static File createTempFile( String prefix, String suffix, File directory ) throws IOException Legt eine neue Datei im gewünschten Verzeichnis an. Der Dateiname setzt sich aus einem benutzerdefinierten Präfix, einer Zufallsfolge und einem Suffix zusammen.

Galileo Computing - Zum Seitenanfang

13.1.8 Dateien und Verzeichnisse löschen Zur nächsten ÜberschriftZur vorigen Überschrift

Mit Hilfe der Funktion delete() auf einem File-Objekt lässt sich eine Datei oder ein Verzeichnis entfernen. Diese Methode löscht wirklich! Sie ist nicht so zu verstehen, dass sie true liefert, falls die Datei potenziell gelöscht werden kann. Konnte die Laufzeitumgebung delete() nicht ausführen, so sollte die Rückgabe false sein. Ein zu löschendes Verzeichnis muss leer sein, andernfalls kann das Verzeichnis nicht gelöscht werden. Unsere unten stehende Implementierung geht dieses Problem so an, dass sie rekursiv die Unterverzeichnisse löscht.


class java.io.File 
implements Serializable, Comparable<File>

  • boolean delete() Löscht die Datei oder das leere Verzeichnis.
  • void deleteOnExit() Löscht die Datei/das Verzeichnis, wenn die virtuelle Maschine korrekt beendet wird. Einmal vorgeschlagen, kann das Löschen nicht mehr rückgängig gemacht werden. Falls die JVM vorzeitig die Grätsche macht – Reinigungsfachkraft stolpert über Kabel –, kann natürlich die Datei möglicherweise noch immer nicht gelöscht sein, was insbesondere für temporäre Dateien, die über createTempFile() angelegt wurden, eventuell lästig wäre.

Hinweis Hinweis Auf manchen Systemen liefert delete() die Rückgabe true, die Datei ist aber nicht gelöscht. Der Grund kann eine noch geöffnete Datei sein, mit der zum Beispiel ein Eingabestrom verbunden ist und die dadurch gelockt ist.


Rekursiv Verzeichnisse löschen

Die delete()-Funktion funktioniert auf File-Objekten, die Dateien und auch Verzeichnisse repräsentieren. Doch wenn Verzeichnisse nicht leer sind, wird delete() nicht auch noch alle Dateien in diesem Verzeichnis inklusive aller Unterverzeichnisse löschen. Das muss von Hand erledigt werden, lässt sich aber in wenigen Programmcodezeilen rekursiv umsetzen. Eine Funktion deleteTree() soll einen Baum inklusive Unterverzeichnisse löschen. list() liefert ein Feld aller Elemente in dem Unterverzeichnis, und falls ein Element wiederum ein Verzeichnis ist, wird wieder deleteTree() auf diesem aufgerufen.

Listing 13.10 com/tutego/insel/io/file/DeleteTree.java

package com.tutego.insel.io.file; 
 
import java.io.File; 
 
public class DeleteTree 
{ 
  public static void deleteTree( File path ) 
  { 
    for ( File file : path.listFiles() ) 
    { 
      if ( file.isDirectory() ) 
        deleteTree( file ); 
      else 
        file.delete(); 
    } 
    path.delete(); 
  } 
 
  public static void main( String[] args ) 
  { 
    deleteTree( new File("c:/ati/") ); 
  } 
}

Galileo Computing - Zum Seitenanfang

13.1.9 Verzeichnisse nach Dateien iterativ durchsuchen Zur nächsten ÜberschriftZur vorigen Überschrift

Im Kapitel 12 haben wir die Datenstrukturen List und Stack kennengelernt, die uns jetzt helfen sollen, ein Verzeichnis inklusive aller Unterverzeichnisse weiter nach unten zu gehen. Dabei sollen Dateien gefunden werden, deren Dateinamen auf regulären Ausdrücken »matchen«. Ein List-Objekt speichert bereits gefundene Dateien, und ein Stack-Object merkt sich via Tiefensuche das aktuelle Verzeichnis, in dem der Algorithmus gerade steht. Anders als bei DeleteTree nutzt diese Implementierung keine rekursiven Funktionsaufrufe.

Listing 13.11 com/tutego/insel/io/file/FileFinder.java

package com.tutego.insel.io.file; 
 
import java.io.*; 
import java.util.*; 
import java.util.regex.Pattern; 
 
public class FileFinder 
{ 
  public static List<File> find( String start, String extensionPattern ) 
  { 
    List<File> files = new ArrayList<File>( 1024 ); 
    Stack<File> dirs = new Stack<File>(); 
    File startdir = new File( start ); 
    Pattern p = Pattern.compile( extensionPattern, Pattern.CASE_INSENSITIVE ); 
 
    if ( startdir.isDirectory() ) 
      dirs.push( startdir ); 
 
    while ( dirs.size() > 0 ) 
      for ( File file : dirs.pop().listFiles() ) 
        if ( file.isDirectory() ) 
          dirs.push( file ); 
        else 
          if ( p.matcher(file.getName()).matches() ) 
            files.add( file ); 
 
    return files; 
  } 
}

Eine Nutzung der Utility-Funktion ist einfach, wie etwa die folgenden Zeilen zeigen, um Dokumente mit den Dateiendungen .gif und .jpg zu finden.

Listing 13.12 com/tutego/insel/io/file/FileFinderDemo.java, main()

String path = new File( System.getProperty("user.dir") ).getParent(); 
 
System.out.println( "Looking in path: " + path ); 
 
List<File> files = FileFinder.find( path, "(.*\\.gif$)|(.*\\.jpg$)" ); 
 
System.out.printf( "Found %d file%s.%n", 
                   files.size(), files.size() == 1 ? "" : "s" ); 
 
for ( File f : files ) 
  System.out.println( f.getAbsolutePath() );

Galileo Computing - Zum Seitenanfang

13.1.10 URL- und URI-Objekte aus einem File-Objekt ableiten Zur nächsten ÜberschriftZur vorigen Überschrift

Da es bei URL-Objekten recht häufig vorkommt, dass eine Datei die Basis ist, wurde die Methode toURI() in die Klasse File aufgenommen, über die sich mit toURL() ein URL-Objekt aufbauen lässt. (Eine Methode toURL() gibt es auch, nur ist diese in Java 6 veraltet.)

File f = new File( "C:/Dokumente und Einstellungen/" ); 
URL u = f.toURL();        // veraltet! 
System.out.println( u );  // file:/C:/Dokumente und Einstellungen/ 
u = f.toURI().toURL(); 
System.out.println( u );  // file:/C:/Dokumente%20und%20Einstellungen/

class java.io.File 
implements Serializable, Comparable<File>

  • URI toURI() Liefert ein URI-Objekt vom File-Objekt, über das toURL() ein URL-Objekt generiert.

Galileo Computing - Zum Seitenanfang

13.1.11 Mit Locking Dateien sperren Zur nächsten ÜberschriftZur vorigen Überschrift

Damit eine Datei gegen konkurrierenden parallelen Zugriff geschützt ist, lässt sie sich über Locking absichern. Um einen Lock zu erwerben, ist die Klasse FileChannel und deren Funktion lock() zu nutzen. Um zu testen, ob eine gegebene Datei gelockt ist, lässt sich tryLock() verwenden – etwa in folgender Funktion:

Listing 13.13 com/tutego/insel/io/file/FileUtils.java, isLocked()

public static boolean isLocked( String filename ) 
{ 
  try 
  { 
    FileLock lock = new RandomAccessFile( filename, "r" ).getChannel().tryLock(); 
    lock.release(); // ignore ClosedChannelException 
  } 
  catch( IOException e ) { 
     return false; 
  } 
  return true; 
} [Zum Beispiel mit dem Alleskönner fcntl() aus POSIX-Standard oder flock() von 4.2 BSD.
] 

Hinweis Hinweis Unter Unix-Systemen gibt es keine eindeutig vorgeschriebene Methode zum File-Locking5 , so dass Sun das Sperren bisher nur so umsetzt, dass zwei Java-Programme sich gegenseitig nicht in die Quere kommen, es aber sein kann, dass ein anderes Unix-Programm diesen Lock nicht respektiert. So kann unter Unix eine Datei von mehreren Seiten gelesen werden, selbst wenn ein Java-Programm sie aktuell beschreibt. Auch kann eine Datei auf dem Dateisystem gelöscht werden, selbst wenn das Java-Programm sie noch offen hält. Das Windows-Betriebssystem unterstützt hingegen Locks. Wenn ein Prozess keinen Lock auf die Datei besitzt, kann der Prozess die Datei auch nicht lesen.



Galileo Computing - Zum Seitenanfang

13.1.12 Sicherheitsprüfung Zur nächsten ÜberschriftZur vorigen Überschrift

Wir müssen uns der Tatsache bewusst sein, dass verschiedene Methoden eine SecurityException auslösen können, sofern ein Security-Manager die Dateioperationen überwacht. Security-Manager kommen beispielsweise bei Applets zum Zuge. Folgende Methoden sind Kandidaten für eine SecurityException: exists(), canRead(), canWrite(), isDirectory(), lastModified(), length(), mkdir(), mkdirs(), list(), delete() und renameFile().


Galileo Computing - Zum Seitenanfang

13.1.13 Mime-Typen mit dem JavaBeans Activation Framework (JAF) Zur nächsten ÜberschriftZur vorigen Überschrift

Eine Erkennung der MIME-Typen ist mit der Standardbibliothek möglich, seitdem Sun in Java 6 das JavaBeans Activation Framework (JAF) integriert hat. [Für Versionen vor Java 6 bietet es Sun unter http://java.sun.com/products/javabeans/jaf/ an. Das Java-Archiv activation.jar muss dann in den Klassenpfad aufgenommen werden. Die JAF wird auch beim Verschicken von E-Mails über die JavaMail API und bei Web-Services mit Apache Axis benötigt. ] Die Klasse javax.activation.MimetypesFileTypeMap ermittelt den MIME-Type für eine Datei.

Listing 13.14 com/tutego/insel/io/file/PrintMimeType.java, main()

File f = new File(  
  "C:/Programme/Java/jdk1.6.0/demo/applets/ImageMap/images/jim.graham.gif" ); 
MimetypesFileTypeMap map = new MimetypesFileTypeMap(); 
System.out.println( map.getContentType( f ) );             // image/gif

Eine zusätzliche Open-Source-Bibliothek unter der LGPL-Lizenz ist JMimeMagic unter http://jmimemagic.sf.net/. Über eine XML-Datei werden die Typen und Binärkennungen kodiert.


Galileo Computing - Zum Seitenanfang

13.1.14 Zugriff auf SMB-Server mit jCIFS topZur vorigen Überschrift

Microsoft Windows nutzt zur Datei- und Verzeichnisfreigabe, zur Freigabe von Druckern und Kommunikationsschnittstellen das Protokoll SMB (Server Message Block). Es ist weit verbreitet, und jede neuere Windows-Version (ab Win95 und NT) lässt sich als Client und Server konfigurieren – gleichzeitig gibt es unter Unix das populäre Samba, einen SMB-Server unter Open-Source, von Andrew Tridgell.

Die Geschichte des SMB-Protokolls geht auf das Jahr 1985 zurück, als man bei IBM über ein verteiltes Dateisystem nachdachte. Von 1987 an taten sich Microsoft und Intel zusammen und dokumentierten ihre Vorstellung im Networks/OpenNET-FILE SHARING PROTOCOL. Das Protokoll hat sich mit den Jahren ständig verändert (Core Protocol, LAN Manager). Die wichtigste SMB-Variante dürfte NT LM 0.12 sein. In jüngerer Zeit haben Microsoft und eine Gruppe weiterer Hersteller (DEC, Data General, SCO, Network Appliance Corp, ...) das Protokoll weiterentwickelt (embrace, extend) und nannten es 1996 CIFS. Samba implementiert den Dialekt NT LM 0.12.

jCIFS

Mit Hilfe der jCIFS-SMB-Bibliothek (http://jcifs.samba.org/) kann ein Java-Programm auf Datei- und Verzeichnisfreigaben zugreifen und Freigaben auflisten. jCIFS ist eine erweiterte Implementierung von CIFS und unterstützt Unicode, Batching, verschlüsselte Authentifizierung, Transactions, Remote Access Protocol (RAP) und Weiteres. Die Bibliothek steht unter der LGPL.

Die Klassen jcifs.smb.SmbFile, SmbFileInputStream und SmbFileOutputStream verhalten sich ähnlich wie java.io.File, FileInputStream und FileOutputStream. Sie werden mit einem Dateipfad (URL) parametrisiert, der mit smb:// beginnt. Um eine Datei zu beziehen, muss vorher der Server spezifiziert werden. Dazu dienen Eigenschaften wie WINS. Sie werden mit Config.setProperty("wins", "IP-Adresse"); gesetzt.

Ein Beispiel soll zeigen, wie sich eine Datei auslesen und umkopieren lässt:

InputStream in = 
  new SmbFileInputStream( "smb://user:passwd@host/c/My Documents/doc.txt" ); 
byte[] b = new byte[ 8192 ]; 
for ( int n; ( n = in.read( b )) > 0; ) 
  out.write( b, 0, n );

Neben den Lese-/Schreiboperationen kann man wie bei java.io.File eine Liste der Inhalte geben, Verzeichnisse anlegen und so weiter.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.






<< zurück



Copyright © Galileo Press 2008
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, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de