HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 300 – 00 – TH – 04 ------------------------------------------------------------------------------------ Programmieren in Java Kapitel 3 3. Elementare Programmfunktionalitäten 3.1. Zugriff zu Programmparametern 3.2. Standard-Ein-und-Ausgabe (Konsolen-E/A) 3.3. Interaktion mit dem Laufzeitsystem 3.4. Exceptions 3.5. Dateizugriff FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK BEREICH DATENTECHNIK V – JV – 311 – 00 – TH – 01 ----------------------------------------------------------------------------------- Zugriff zu Programmparametern in Java • Programparameter (Kommandozeilenparameter) ◇ Einem Programm können i.a. beim Aufruf Parameter übergeben werden. Programmparameter ◇ Diese werden beim Aufruf aus der Kommandozeile durch Blanks getrennt an den eigentlichen Programmaufruf angehängt. Kommandozeilenparameter Bei Java-Programmen werden sie nach dem Namen der Start-Klasse angegeben. ◇ Beispiel : java Echo Sie tanzte nur einen Sommer Kommandozeilenparameter sind : Sie tanzte nur einen Sommer • Zugriff im Programm ◇ Die Programmparameter (ohne Namen der Startklasse !) werden in einem String-Array zusammengefasst. Eine Referenz auf dieses Array wird der main()-Methode der Startklasse als Parameter übergeben. ◇ Die main()-Methode der Startklasse muß daher mit einem Parameter (Argument) vom Typ String[] definiert werden : public static void main(String[] args) { // ... } ◇ Innerhalb der main()-Methode stehen damit die Programmparameter als Komponenten des String-Arrays args zur Verfügung. ◇ Die Anzahl der Programmparameter (= Länge des String-Arrays) ist ermittelbar mittels args.length. • Beispiel : // Echo.java class Echo { public static void main(String[] args) { for (int i=0; i<args.length; i++) System.out.println("Parameter "+ i + " : " + args[i]); } } Beispiel eines Programm-Aufrufs : E:\java\fhm\ee\vorl>java Echo Sie tanzte nur einen Sommer Parameter Parameter Parameter Parameter Parameter 0 1 2 3 4 : : : : : Sie tanzte nur einen Sommer E:\java\fhm\ee\vorl> FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 321 – 00 – TH – 04 ------------------------------------------------------------------------------------ Standard-Ein- und Ausgabe in Java (1) • Grundsätzliches zum I/O-Model von Java ◇ Eine Programm-Ein- und Ausgabe findet üblicherweise über Dateien und/oder Geräte statt. ◇ Java betrachtet sowohl Geräte als auch Dateien grundsätzlich als sequentielle Folge von Bytes (Byte-Stream). Da Java Zeichen und Strings im Unicode darstellt, bietet die Sprache auch die Möglichkeit Textdateien/Text-Geräte als sequentielle Folge von Unicode-Zeichen (Unicode-Stream) zu interpretieren. ◇ Programmintern wird eine Datei bzw ein Gerät durch ein Objekt einer Stream-Klasse repräsentiert. ◇ Es gibt zahlreiche verschiedene Stream-Klassen, die jeweils unterschiedliche Eigenschaften modellieren. Alle Stream-Klassen sind im Package java.io enthalten. ◇ Vier abstrakte Klassen sind Basisklassen aller übrigen Stream-Klassen : ▻ InputStream Basisklasse für Klassen zum byteweisen Lesen (Lesen von Byte-Streams) ▻ Reader Basisklasse für Klassen zum zeichenweisen Lesen (Lesen von Unicode-Zeichen-Streams) ▻ OutputStream Basisklasse für Klassen zum byteweisen Schreiben (Schreiben in Byte-Streams) ▻ Writer Basisklasse für Klasse zum zeichenweisen Schreiben (Schreiben in Unicode-Zeichen-Streams) Diese Klassen definieren jeweils ein generelles Interface zur Verwendung der Objekte der entsprechenden abgeleiteten Klassen. ◇ Konverter-Klassen (Brücken-Klassen) erlauben einen Übergang zwischen Byte-Streams und Unicode-ZeichenStreams : ▻ InputStreamReader (abgeleitet von Reader) Klasse zum zeichenweisen Lesen aus Byte-Streams ▻ OutputStreamWriter (abgeleitet von Writer) Klasse zum zeichenweisen Schreiben in Byte-Streams • Standard-Ein- und Ausgabe-Objekte ◇ Für die Standard-Eingabe, die Standard-Ausgabe und die Standard-Fehlerausgabe werden für jedes Programm automatisch Stream-Objekte angelegt, d.h. die entsprechenden Streams (üblicherweise Tastatur und Bildschirm des Konsolengeräts) sind implizit geöffnet. Aus historischen Gründen handelt es sich hierbei um Byte-Stream-Objekte. ◇ Referenzen auf diese Stream-Objekte stehen als öffentliche statische Datenkomponenten der – nicht instanzierbaren – Klasse System (im Package java.lang) zur Verfügung : ▻ public static final InputStream in Standard-Eingabe-Objekt ▻ public static final PrintStream out Standard-Ausgabe-Objekt ▻ public static final PrintStream err Standard-Fehlerausgabe-Objekt Die Klasse PrintStream ist eine von OutputStream – indirekt – abgeleitete Klasse. Sie ermöglicht das Schreiben von Werten der einfachen Datentypen und von Objekten beliebiger Klassen (nach Umwandlung in eine String-Repräsentation) sowie direkt von Strings in einen Byte-Stream. Hierfür stellt sie die mehrfach überladenen Funktionen print() und println() (nicht explizit formatierbare Ausgabe) sowie die Methode printf() (formatierte Ausgabe) zur Verfügung. ◇ Ab dem JDK 6.0 kann als Alternative für den Zugriff zum Konsolengerät auch ein vordefiniertes Objekt der Klasse Console eingesetzt werden. FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 322 – 00 – TH – 03 ------------------------------------------------------------------------------------ Standard-Ein- und Ausgabe in Java (2) • Schreiben in die Standard-Ausgabe und Standard-Fehlerausgabe ◇ Mittels der für die Standard-Stream-Objekte ▻ System.out (Standard-Ausgabe, Klasse PrintStream) ▻ System.err (Standard-Fehlerausgabe, Klasse PrintStream) aufgerufenen Methoden ▻ public void print(...) ▻ public void println(...) ▻ public PrintStream printf(String form, Object... args) (ab dem JDK 5.0) ▻ public PrintStream format(String form, Object... args) (ab dem JDK 5.0) ◇ Die Methoden print() und println() haben jeweils einen Parameter und ermöglichen die Ausgabe - von boolean-, char-, double-, float-, int- und long-Werten - von char-Arrays - von Strings (Objekte der Klasse String) - sowie der String-Repräsentation (Methode toString()) von Objekten beliebiger Klassen ◇ Die Methode println() ergänzt die Ausgabe um ein Zeilenendezeichen. Sie lässt sich auch ohne Parameter aufrufen. In diesem Fall bewirkt sie lediglich einen Übergang in eine neue Zeile. ◇ Beispiel : class StdOutDemo1 { public static void main(String[] args) { boolean b = true; char c = 'Z'; int i = 399127; long l = 124L; float f = 2.25E-2f; double d = 0.0/0.0; String s = "Hallo !"; StdOutDemo1 sod = new StdOutDemo1(); System.out.print(b); System.out.println(); System.out.println(c); System.out.println(i); System.out.println(l); System.out.println(f); System.out.println(d); System.out.println(s); System.out.println(sod); } } Ausgabe : true Z 399127 124 0.0225 NaN Hallo ! StdOutDemo1@eee36c ◇ Die Anwendung der String-Konkatenation in Verbindung mit der automatischen Umwandlung von beliebigen Datenwerten und Objekten in eine String-Repräsentation bei ihrem Auftritt in Konkatenations-Aus drücken (Methode toString()) erlaubt die Ausgabe mehrerer Werte/Objekte mit einem Methodenaufruf. Achtung : Der +-Operator (Konkatenation, Addition) ist links-rechts-assoziativ. Damit bei mehrfacher Konkatenation tatsächlich der richtige Gesamtstring entsteht, muss bei der ersten (am weitesten links stehenden) Verknüpfungsoperation wenigstens ein String beteiligt sein. Beispiel : class StdOutDemo2 { public static void main(String[] args) { System.out.println(1 + '+' + 1 + " ergibt " + 2); System.out.println(1 + "+" + 1 + " ergibt " + 2); } } Ausgabe : 45 ergibt 2 1+1 ergibt 2 FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 323 – 01 – TH – 04 ------------------------------------------------------------------------------------ Standard-Ein- und Ausgabe in Java (3 - 1) • Formatierte Ausgabe (ab dem JDK 5.0) ◇ Mittels der PrintStream-Methoden public PrintStream printf(String form, Object... args); public PrintStream format(String form, Object... args); Rückgabewert bei beiden Methoden : aktuelles PrintStream-Objekt ◇ Beide Methoden sind in der Wirkung identisch. Sie ermöglichen eine C-ähnliche formatierte Ausgabe ◇ Der erste Parameter form ist der Format-String. Er enthält – analog zum Format-String der C-Funktion printf() – die einzelnen Formatangaben (format specifier) für die auszugebenden Werte/Objekte. Durch die Formatangaben wird auch der Typ bzw die Darstellungsart der Ausgabe-Werte festgelegt Zusätzlich kann der Format-String weiteren Text enthalten, der direkt ausgegeben wird. ◇ Die zweite Parameter-Angabe Object... args bedeutet, dass eine beliebige Anzahl (auch keine) weiterer Parameter beliebigen Referenz-Typs folgen darf. Diese Parameter (Argumente) legen die Werte fest, die entsprechend des jeweils spezifizierten Formats auszugeben sind. Für jede Formatangabe muss ein passendes Argument übergeben werden. Die Typen dieser Argumente müssen zu den entsprechenden Angaben im Format-String passen. Überflüssige Argumente werden ignoriert Als Parameter können auch Werte einfacher Datentypen auftreten, da sie mittels Autoboxing automatisch in Objekte der zugehörigen Wrapper-Klassen umgewandelt werden. ◇ Syntax der Formatangaben (vereinfacht) : % [flags][width][.precision]conversion ▻ conversion (Konvertierungszeichen) legt die Formatierungsart und/oder den Typ der Ausgabe fest und schließt eine Formatangabe ab Die wichtigsten Konvertierungszeichen sind : b d o x c e f g oder B oder X oder C oder E oder G s oder S n logischer Wert ganzzahliger Wert in Dezimaldarstellung ganzzahliger Wert in Oktaldarstellung ganzzahliger Wert in Sedezimaldarstellung Unicode-Zeichen Gleitpunkt-Wert in Exponentialdarstellung Gleitpunkt-Wert in Dezimalbruchdarstellung Gleitpunkt-Wert in Dezimalbruchdarstellung oder Exponentialdarstellung (abhängig von Wert und Genauigkeit) String (der String, der durch die jeweilige Methode toString() erzeugt wird) Zeilenendezeichen Bei einem Großbuchstaben als Konvertierungszeichen werden alle Buchstaben als Großbuchstaben ausgegeben ▻ flags (Steuerflags) modifizieren das Ausgabeformat, sie können gegebenenfalls miteinander kombiniert werden Die wichtigsten Steuerflags sind : + 0 ' ' (Blank) linksbündige Ausgabe auch positive Werte werden mit Vorzeichen ausgegeben (nur für Zahlen anwendbar) Ausgabe führender Nullen (nur für Zahlen anwendbar) Ausgabe positiver Werte mit führendem Blank (nur für Zahlen anwendbar) ▻ width (Ausgabefeldbreite) legt die minimale Ausgabefeldbreite fest ▻ precision (Genauigkeit) legt i.a. die maximale Ausgabefeldbreite fest, bei Gleitpunktzahlen jedoch die Anzahl der Nachpunktstellen (Ausnahme : beim Konvertierungszeichen g bzw G wird die Gesamtzahl der Ziffern festgelegt), bei Strings : Anzahl der auszugebenden Zeichen des Strings ◇ Nichtzulässige Zeichen in einer Formatangabe sowie fehlende oder zu einer Formatangabe nicht-kompatible Argumente führen zum Werfen einer IllegalFormatException. FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 323 – 02 – TH – 02 ------------------------------------------------------------------------------------ Standard-Ein- und Ausgabe in Java (3 - 2) • Ergänzende Anmerkungen zur formatierten Ausgabe (ab dem JDK 5.0) ◇ Es existieren noch weitere Möglichkeiten der Formatierung (insbesondere auch für Datums- und Zeitdarstellungen). Genauere Informationen können der API-Dokumentation zur Klasse Formatter (Package java.util) entnommen werden. ◇ Zur Erzeugung von formatierten Ausgaben kann auch die Klasse Formatter eingesetzt werden : Mit Objekten dieser Klasse ist es u.a. möglich ▻ formatierte Ausgaben direkt in Dateien oder OutputStream- sowie PrintStream-Objekten vorzunehmen ▻ formatierte Strings zu erzeugen (als Objekte der Klassen StringBuffer oder StringBuilder). Diese Strings können dann explizit ausgegeben (print() oder println()) bzw in Dateien geschrieben werden. • Demonstrationsprogramm zur formatierten Ausgabe : // FormOutpDemo1.java // Demonstrationsprogramm zur formatierten Ausgabe public class FormOutpDemo1 { void show() { int anz = 10; double summe = 99.98765; float anteil = 0.00005432f; String type = "Airbus A-380"; System.out.println("0123456789012345678901234567890123456789"); System.out.printf("Anzahl : %5d Summe : %8.3e\n", anz, summe); System.out.format("Anzahl : %5d Summe : %8.3e\n", anz, summe); System.out.printf("Anzahl : %-5d Summe : %8.3f\n", anz, summe); System.out.printf("Anzahl : %0+5d Summe : %08.3f\n", anz, summe); System.out.printf("Anteil : % .4g\n", anteil); System.out.printf("Anteil : %.4E\n", anteil); System.out.printf("Anteil : %.4f\n", anteil); System.out.printf("Typ : %s\n", type); System.out.printf("Typ : %15s\n", type); System.out.printf("Typ : %5s\n", type); System.out.printf("Typ : %5.6S\n", type); System.out.printf("Typ : %8.6s\n", type); System.out.printf("%B\n", true); } public static void main(String[] args) { FormOutpDemo1 demo = new FormOutpDemo1(); demo.show(); } Ausgabe des Programms : 0123456789012345678901234567890123456789 Anzahl : 10 Summe : 9.999e+01 Anzahl : 10 Summe : 9.999e+01 Anzahl : 10 Summe : 99,988 Anzahl : +0010 Summe : 0099,988 Anteil : 5.432e-05 Anteil : 5.4320E-05 Anteil : 0,0001 Typ : Airbus A-380 Typ : Airbus A-380 Typ : Airbus A-380 Typ : AIRBUS Typ : Airbus TRUE FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 324 – 00 – TH – 04 ----------------------------------------------------------------------------------- Standard-Ein- und Ausgabe in Java (4) • Lesen aus der Standard-Eingabe ◇ Das für die Standard-Eingabe definierte Stream-Objekt System.in steht als Instanz der Klasse InputStream zur Verfügung. Diese Klasse besitzt zum Einlesen lediglich die mehrfach überladene Methode read(), mit der nur einzelne Bytes oder eine Gruppe von Bytes (Byte-Array) eingelesen werden können. ◇ Üblicherweise soll von der Standard-Eingabe aber Text eingelesen werden, der vom Programm entweder als Wert eines einfachen Datentyps oder direkt als String interpretiert und verwendet werden soll. D.h. also, es müssen Zeichenfolgen (Datentyp char) und nicht Bytefolgen (Datentyp Byte) eingelesen werden. ◇ Der über System.in erhältliche Byte-Stream muß also in einen Unicode-Stream umgewandelt werden. Diese erfolgt mittels eines Objekts der Klasse InputStreamReader. Dem Konstruktor zur Erzeugung dieses Objekts ist das zugrundeliegende InputStream-Objekt, hier also System.in als Parameter zu übergeben. Die Klasse InputStreamReader erlaubt mittels der überladenen Methode read() das Einlesen von Einzelzeichen bzw Zeichen-Arrays. Einlesen von Einzelzeichen : public int read() throws IOException Funktionswert : gelesenes Zeichen bzw –1 bei Eingabeende ◇ Um Strings einlesen zu können, wird ein BufferedReader-Objekt benötigt. Dieses lässt sich unter Verwendung des InputStreamReader-Objekts, das dem Konstruktor als Parameter zu übergeben ist, erzeugen (Der Konstruktor der Klasse BufferedReader benötigt ein Reader-Objekt als Parameter, die Klasse InputStreamReader ist von Reader abgeleitet). Die Klasse BufferedReader stellt neben der überladenen Methode read() zum Einlesen von Einzelzeichen und Zeichen-Arrays eine Methode zum zeilenweisen Lesen zur Verfügung : public String readLine() throws IOException Funktionswert : eingelesene Zeile als String-Objekt (ohne Zeilenende-Zeichen) bzw null wenn das EingabeEnde (EOF, Dateiende) erreicht ist. Bei der Anwendung dieser Methode (wie auch aller anderen Lese-Methoden) ist zu berücksichtigen, dass bei Auftritt eines I/O-Fehlers, eine Exception vom Typ IOException geworfen wird. Diese ist entweder in der aufrufenden Funktion zu fangen oder von dieser weiterzuwerfen. ◇ Darstellung als Klassendiagramm : BufferedReader +read():int +readLine():String InputStreamReader +read():int InputStream +read():int ◇ Beispiel : // EchoLines.java import java.io.*; class EchoLines { public static void main(String[] args) throws IOException { BufferedReader stdin = new BufferedReader( new InputStreamReader(System.in)); String line; while ((line=stdin.readLine()) != null) System.out.println(line); } } FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 325 – 00 – TH – 04 ------------------------------------------------------------------------------------ Standard-Ein- und Ausgabe in Java (5) • Lesen aus der Standard-Eingabe, Forts. ◇ Zum Einlesen von Werten der einfachen Datentypen muß der eingelesene String entsprechend dem Datentyp interpretiert und in die interne Wertedarstellung umgewandelt werden. Hierfür stehen entsprechende statische Methoden der jeweiligen Wrapper-Klassen zur Verfügung : ▻ Klasse Byte : public static byte parseByte(String str) throws NumberFormatException; ▻ Klasse Short : public static short parseShort(String str) throws NumberFormatException; ▻ Klasse Integer : public static int parseInt(String str) throws NumberFormatException; ▻ Klasse Long : public static long parseLong(String str) throws NumberFormatException; ▻ Klasse Float : public static float parseFloat(String str) throws NumberFormatException; ▻ Klasse Double : public static double parseDouble(String str) throws NumberFormatException; Diese Methoden liefern die interne Darstellung des durch den Parameter str repräsentierten Werts des jeweiligen Typs als Funktionswert zurück. Sie erzeugen eine Exception vom Typ NumberFormatException, wenn str keinen entsprechenden Zahlenwert darstellt. ◇ Zur Umwandlung eines Strings in einen boolean-Wert müssen zwei Methoden der Wrapper-Klasse Boolean eingesetzt werden : ▻ Klasse Boolean : public static Boolean valueOf(String str); Diese Methode erzeugt ein Boolean-Objekt, das den Wert true repräsentiert, wenn der Parameter str gleich dem String "true" ist , wobei Groß-/Kleinschreibung ignoriert wird ("True" oder "TRUE" z.B. führen ebenfalls zum Wert true). Für jeden anderen Wert von str repräsentiert das erzeugte Boolean-Objekt den Wert false. ▻ Klasse Boolean : public boolean booleanValue(); Diese Methode gibt den durch ein Boolean-Objekt repräsentierten boolean-Wert zurück. ◇ Beispiel : import java.io.*; class StdInpDemo { public static void main(String[] args) throws IOException { int a, b; BufferedReader stdin = new BufferedReader( new InputStreamReader(System.in)); System.out.print("Wert von a ? "); a = Integer.parseInt(stdin.readLine()); System.out.print("Wert von b ? "); b = Integer.parseInt(stdin.readLine()); System.out.println("a+b = " + (a+b)); System.out.print("Boolean-Wert ? "); String s = stdin.readLine(); boolean bw = Boolean.valueOf(s).booleanValue(); System.out.println("Eingabe war : " + bw); } } Beispiel für Ein- und Ausgabe des Programms : Wert von a Wert von b a+b = 634 Boolean-Wert Eingabe war ? 213 ? 421 ? True : true ◇ Eine alternative, flexiblere und einfachere Möglichkeit zum Einlesen von Werten einfacher Datentypen bietet die mit dem JDK 5.0 eingeführte Klasse Scanner FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 326 – 01 – TH – 03 ------------------------------------------------------------------------------------ Die Klasse Scanner in Java (1) • Allgemeines zur Klasse Scanner ◇ Bestandteil des Packages java.util, ab dem JDK 5.0 vorhanden ◇ Objekte der Klasse Scanner dienen zum Zergliedern und Interpretieren von Zeichenfolgen. ◇ Die von Scanner-Objekten bearbeitbaren Zeichenfolgen können aus unterschiedlichen Eingabe-Quellen stammen (Dateien, sonstige Eingabe-Streams wie z.B. die Standard-Eingabe, Strings). Die jeweilige Quelle muss beim Erzeugen eines Scanner-Objekts festgelegt werden. ◇ Scanner-Objekte zerlegen ihre Eingabe-Zeichenfolge in Teil-Abschnitte (token). Die Zeichen(-muster), die als Trennzeichen zwischen den Abschnitten interpretiert werden (delimiter pattern), lassen sich konfigurieren. Defaultmässig werden Whitespace-Character verwendet. ◇ Die einzelnen Teil-Abschnitte stehen als Strings zur Verfügung und können als Werte eines einfachen Datentyps interpretiert und in die dem jeweiligen Typ entsprechende interne Darstellung umgewandelt werden. ◇ Damit lassen sich Scanner-Objekte sehr elegant zum Einlesen von Werten der einfachen Datentypen aus der Standard-Eingabe einsetzen, insbesondere auch dann, wenn in einer Eingabezeile mehrere einzulesende Werte enthalten sind. • Konstruktoren der Klasse Scanner (Auswahl) public Scanner(File source) Erzeugung eines Scanner-Objekts, dessen Eingabe-Quelle die durch source spezifizierte Datei ist public Scanner(Readable source) Erzeugung eines Scanner-Objekts, dessen Eingabe-Quelle das durch source spezifizierte Objekt ist. Dieses Objekt muss das Interface Readable implementieren public Scanner(InputStream source) Erzeugung eines Scanner-Objekts, dessen Eingabe-Quelle das durch source spezifizierte InputStream-Objekt ist public Scanner(String source) Erzeugung eines Scanner-Objekts, dessen Eingabe-Quelle der durch source spezifizierte String ist. • Memberfunktionen der Klasse Scanner (Auswahl) public String nextLine() Rückgabe des Rests der aktuellen Eingabe-Zeile public boolean hasNextLine() Überprüfung, ob eine weitere Eingabe-Zeile vorhanden ist, wenn ja true public String next() Rückgabe des nächsten Teil-Abschnitts (token) der Eingabe-Zeichenfolge public boolean hasNext() Überprüfung ob ein weiterer Teil-Abschnitt vorhanden ist, wenn ja true public byte nextByte() public short nextShort() public int nextInt() public long nextLong() public float nextFloat() public double nextDouble() public boolean nextBoolean() Interpretation des nächsten Teil-Abschnitts der Eingabe-Zeichenfolge als Wert des jeweiligen Typs und Rückgabe der internen Darstellung dieses Wertes Jede der Funktionen wirft eine Exception vom Typ InputMismatchException, wenn der Teil-Abschnitt sich nicht als Wert des jeweiligen Typs interpretieren lässt (boolean-Werten können mit Gross- und/oder Kleinbuchstaben dargestellt werden) FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 326 – 02 – TH – 01 ------------------------------------------------------------------------------------ Die Klasse Scanner in Java (2) • Demonstrationsbeispiele zur Klasse Scanner ◇ Programm EchoLinesScanDemo // EchoLinesScanDemo.java // Echo der von der Standard-Eingabe eingelesenen Zeilen in die Standard-Ausgabe // Verwendung der Klase Scanner import java.util.*; public class EchoLinesScanDemo { public static void main(String[] args) { Scanner scan = new Scanner(System.in); while (scan.hasNextLine()) System.out.println(scan.nextLine()); } } ◇ Programm StdInpScanDemo // StdInpScanDemo.java // Demonstrationsprogramm zum Einlesen von der Standard-Eingabe // Verwendung der Klasse Scanner import java.util.*; public class StdInpScanDemo { public static void main(String[] args) { int a, b; Scanner scan = new Scanner(System.in); System.out.print("Zwei Integer-Werte a und b ? "); a = scan.nextInt(); b = scan.nextInt(); System.out.println("a+b = " + (a + b)); System.out.print("Boolean-Wert ? "); boolean bw = scan.nextBoolean(); System.out.println("Eingabe war : " + bw); } } ◇ Beispiel für die Ein- und Ausgabe des Programms StdInpScanDemo Zwei Integer-Werte a und b ? 12 25 a+b = 37 Boolean-Wert ? FalsE Eingabe war : false HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 327 – 01 – TH – 04 ------------------------------------------------------------------------------------ Die Klasse Console in Java (1) • Allgemeines zur Klasse Console ◇ Bestandteil des Packages java.io, ab dem JDK 6.0 vorhanden ◇ Die Klasse stellt Methoden zum Zugriff zum Konsolengerät zur Verfügung. Ein Objekt dieser Klasse bildet eine – allerdings nicht immer vorhandene – Alternative zur Verwendung der StandardEin-/Ausgabe-Stream-Objekte. ◇ Die Klasse verfügt über keinen öffentlichen Konstruktor. Sie kann also nicht explizit instanziert werden. Vielmehr erfolgt eine implizite Instanzierung als Singleton durch die JVM, falls mit dieser ein Konsolengerät verbunden ist. Dieses ist u.a. immer dann der Fall, wenn die JVM aus einer Kommandozeile heraus ohne Umleitung der Standard-Einund Ausgabe gestartet wird. Das Konsolengerät wird dann typischerweise durch die Tastatur (Standard-Eingabe) und den Bildschirm (Standard-Ausgabe) gebildet. Wenn die JVM dagegen aus einem anderen Prozess (z.B. Hintergrundprozess oder IDE) heraus gestartet wird, ist mit ihr i.a. kein Konsolengerät verbunden. ◇ Das gegebenenfalls vorhandene einzige Objekt der Klasse Console kann mittels der statischen Methode der Klasse System public static Console console() ermittelt werden. Falls kein Console-Objekt existiert, liefert die Methode null zurück. ◇ Die Klasse Console stellt im wesentlichen die folgenden Funktionalitäten zur Verfügung : ▻ Formatierte Ausgabe ▻ zeilenweises Einlesen ▻ Einlesen von Passwörtern (mit ausgeschalteter Echo-Ausgabe) ▻ Ermittlung der vom Console-Objekt verwendeten Stream-Objekte für die Aus- bzw Eingabe. Bei diesen Objekten handelt es sich um Zeichen-Stream-Objekte. Über sie bestehen weitere Möglichkeiten zur Aus- bzw Eingabe. Anmerkung : Die Standard-Stream-Objekten sind dagegen Byte-Stream-Objekte. ◇ Die Schreib- und Lese-Methoden der Klasse sind synchronisiert, d.h. sie sind für den Einsatz in Multi-Threadanwendungen geeignet. ◇ Die Lese-Methoden geben als Funktionswert null zurück, wenn das Ende des Konsolen-Eingabe-Streams erreicht ist (Eingabe von Ctrl-Z unter Windows bzw Ctrl-D unter Linux/Unix). Wenn anschliessend weitere Zeichen eingegeben werden, können sie mit weiteren Lese-Operationen eingelesen weden. • Memberfunktionen der Klasse Console zur Ermittlung der E/A-Stream-Objekte ◇ public Reader reader() Ermittlung des mit der Konsole verknüpften Eingabe-Stream-Objekts. (Objekt der Klasse Reader) Funktionswert Mittels der von der Klasse Reader implementierten Methoden lassen sich über dieses Eingabe-Stream-Objekt - Einzelzeichen (Methode read()) sowie - Zeichenfolgen (mehrere Methoden read(...), s. API-Dokumentation) einlesen Das Einlesen von Zeichenfolgen über Zeilengrenzen hinweg ist dabei nicht möglich. Da die Klasse Reader das Interface Readable implementiert, lässt sich das Eingabe-Stream-Obekt als Quelle für Scanner-Objekte einsetzen. ◇ public PrintWriter writer() Ermittlung des mit der Konsole verknüpften Ausgabe-Stream-Objekts. (Objekt der Klasse PrintWriter) Funktionswert Die Klasse PrintWriter stellt u.a. die gleichen Methoden print(...), println(...), printf(...) und format(...) zur Verfügung wie die Klasse PrintStream. Damit lassen sich über das Ausgabe-StreamObjekt die gleichen Ausgabe-Operationen wie über die Standard-Ausgabe-Stream-Objekte (System.out und System.err) realisieren. FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 327 – 02 – TH – 02 ------------------------------------------------------------------------------------ Die Klasse Console in Java (2) • Memberfunktionen der Klasse Console zur Ein- und Ausgabe ◇ public Console printf(String form, Object... args) public Console format(String form, Object... args) ▻ formatierte Ausgabe in den Ausgabe-Stream der Konsole ▻ Beide Methoden besitzen die gleiche Funktionalität ▻ Parameter : form Formatstring, enthält die Formatangaben für die auszugebenden Werte/Objekte Syntax der Formatangaben s. Methode printf(...) der Klasse PrintStream args Referenzen auf die auszugebenden Werte/Objekte ▻ Funktionswert : aktuelles Console-Objekt ◇ public void flush() ▻ unmittelbare Ausgabe (Flush) des Buffers des Konsolen-Ausgabe-Streams ◇ public String readLine() ▻ Lesen der nächsten Zeile aus dem Konsolen-Eingabe-Stream ▻ Funktionswert : gelesene Zeile bzw null (wenn am Zeilenende gelesen wird) Das Zeilenende-Zeichen wird nicht mit zurückgegeben ◇ public String readLine(String form, Object... args) ▻ Ausgabe eines formatierten Prompts in den Konsolen-Ausgabe-Stream, anschliessend Lesen der nächsten Zeile aus dem Konsolen-Eingabe-Stream ▻ Parameter : Festlegung des Prompts, s. Parameter der Methode printf(...) (bzw format(...)) ▻ Funktionswert : gelesene Zeile bzw null (wenn am Zeilenende gelesen wird) Das Zeilenende-Zeichen wird nicht mit zurückgegeben ◇ public char[] readPassword() ▻ Lesen eines Passworts aus dem Konsolen-Eingabe-Stream mit ausgeschalteter Echo-Ausgabe ▻ Funktionswert : Gelesenes Passwort (in einem char-Array) bzw null (wenn am Zeilenende gelesen wird) Ein Zeilenende-Zeichen wird nicht mit zurückgegeben ▻ Anmerkung : ◇ Da die Methode das gelesene Passwort als char-Array und nicht als String-Objekt zurückgibt, kann es unmittelbar nach Verwendung im Speicher überschrieben werden public char[] readPassword(String form, Object... args) ▻ Ausgabe eines formatierten Prompts in den Konsolen-Ausgabe-Stream, anschliessend Lesen eines Passworts aus dem Konsolen-Eingabe-Stream mit ausgeschalteter Echo-Ausgabe ▻ Parameter : Festlegung des Prompts, s. Parameter der Methode printf(...) (bzw format(...)) ▻ Funktionswert : Gelesenes Passwort (in einem char-Array) bzw null (wenn am Zeilenende gelesen wird) Ein Zeilenende-Zeichen wird nicht mit zurückgegeben ▻ Anmerkung : Da die Methode das gelesene Passwort als char-Array und nicht als String-Objekt zurückgibt, kann es unmittelbar nach Verwendung im Speicher überschrieben werden FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 327 – 03 – TH – 01 ------------------------------------------------------------------------------------ Demonstrationsprogramm zur Klasse Console in Java • Programm ConsoleDemo // ConsoleDemo.java // Demo-Programm zur Klasse Console import java.io.*; import java.util.*; public class ConsoleDemo { public static void main(String[] args) throws IOException { Console con = System.console(); if (con == null) { System.err.println("JVM besitzt keine Console -- Schade"); } else { System.err.println("JVM besitzt eine Console"); con.printf("%s\n", "Das ist gut"); char[] altPass = con.readPassword("%s ", "altes Passwort ?"); con.printf("Die folgende Ausgabe sollte nicht erfolgen :\n"); con.printf("Das Passwort lautet : %s \n", new String(altPass)); con.writer().print("Das Passwort lautet : "); con.writer().println(altPass); if (!verifyPasswd(altPass)) con.printf("keine Berechtigung\n"); else { char[] neuPass1; char[] neuPass2; do { neuPass1 = con.readPassword("neues Passwort ? "); neuPass2 = con.readPassword("neues Passwort wiederholen : "); } while (!Arrays.equals(neuPass1, neuPass2)); changePasswd(neuPass1); Arrays.fill(neuPass1, ' '); Arrays.fill(neuPass2, ' '); } Arrays.fill(altPass, ' '); } System.out.print("Geben Sie einen beliebigen String ein : "); BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); String s = stdin.readLine(); System.out.println(s); } static void changePasswd(char[] pw) { System.out.println("Passwort geaendert !"); } static boolean verifyPasswd(char[] pw) { return true; } } FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 331 – 00 – TH – 04 ------------------------------------------------------------------------------------ Interaktion mit dem Laufzeitsystem in Java (1) • Die Klasse System ◇ Die Klasse System ist eine nicht-instanzierbare Utility-Klasse (Package java.lang), die einen Zugriff zu einigen Systemeigenschaften ermöglicht. Im wesentlichen stellt sie zur Verfügung : ▻ die Standard-Ein- und Ausgabe-Objekte (öffentliche statische Datenkomponenten) ▻ eine statische Methode zur Ermittlung des Konsolen-Objekts, falls vorhanden (ab JDK 1.6) ▻ statische Methoden zum Ermitteln (und Ändern) der System-Umgebung ("System Properties") ▻ statische Methoden zum Zugriff zu den aktuellen Environment-Variablen des Betriebssystems (ab JDK 1.5) ▻ statische Methoden zum Setzen und Ermitteln des im System installierten SecurityManager-Objekts ▻ statische Utility-Methoden (z.B. zur Ermittlung der aktuellen Zeit, Teilkopieren von Arrays) ▻ einige statische Methoden, die zum aktuellen Runtime-Objekt zugreifen (Aufruf gleichnamiger Methoden) : public static void gc() expliziter Aufruf des Garbage Collectors public static void runFinalization() expliziter Aufruf der finalize()-Methoden aller zur Vernichtung anstehenden Objekte public static void loadLibrary(String libname) Laden der durch libname spezifizierten dynam.Library (native Code) Die Zuordnung zwischen Library, Library-Ort, und Library-Dateiname ist systemabhängig public static void load(String filepath) Laden einer dynam. Library (native Code), die durch den absoluten Dateipfad filepath referiert wird. public static void exit(int status) Beendigung der aktuell laufenden JVM (u. damit des Programms). Der Parameter status ist der Programm-Exit-Code Der Aufruf System.method() ist äquivalent zu Runtime.getRuntime().method() • Ermittlung der aktuellen Zeit ◇ Hierzu dient die statische Methode der Klasse System : public static long currentTimeMillis(); Rückgabewert : Vergangene Zeit seit dem 1.1.1970 UTC, Mitternacht in Millisekunden ◇ Zur Decodierung dieser Zeit in ihre üblicherweise vom Menschen verwendeten Komponenten (Zeit und Datum) kann die Bibliotheks-Klasse Date (Package java.util) eingesetzt werden : ▻ Erzeugung eines Date-Objektes, dessen Konstruktor der von currentTimeMillis() zurückgegebene Wert als Parameter übergeben wird. ▻ Aufruf der Methode public String toString() für dieses Date-Objekt. Der von dieser Methode als Funktionswert erzeugte String enthält die Zeit (und Datum) in folgender Form : dow mon dd hh:mm:ss zzz yyyy ◇ Beispiel : import java.util.Date; class ActTime { public static void main(String[] args) { Date act = new Date(System.currentTimeMillis()); System.out.println("aktuelle Zeit : " + act.toString()); } } aktuelle Zeit : Wed Aug 08 19:38:30 CEST 2007 FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 332 – 00 – TH – 03 ----------------------------------------------------------------------------------- Interaktion mit dem Laufzeitsystem in Java (2) • System-Umgebung (System Properties) ◇ Die System-Umgebung besteht aus System-Eigenschaften (System Properties). Diese werden z. Tl von Standard- Bibliotheks-Klassen benutzt. Sie können aber auch in eigenen Klassen verwendet werden. ◇ Eine System Property hat einen Namen und einen Wert. Der Name ist ein String, der durch jeweils einen Punkt in mehrere Abschnitte unterteilt sein kann. Der Wert ist ebenfalls ein String. • Änderung der System-Umgebung ◇ Für jede JVM existiert ein Satz von Standard System Properties. ◇ Zusätzlich können benutzerdefinierte System Properties beim Programm- (JVM-) Start festgelegt werden. Hierzu dient die –D Option beim Aufruf der JVM. Beispiel : java –DLabor.aktuell=LSW ActTime Hierdurch wird die System Property mit dem Namen "Labor.aktuell" und dem Wert "LSW" zusätzlich gesetzt. ◇ Darüberhinaus können weitere System Properties auch während des Programmlaufs gesetzt werden, vorausgesetzt das SecurityManager-Objekt erlaubt es. Zum Setzen (und Ändern) einer System Property existiert in der Klasse System die statische Methode ▻ public static String setProperty(String key, String val) Die Methode setzt eine System Property mit dem Namen key auf den Wert val. Als Funktionswert gibt die Methode den zuvor gesetzt gewesenen Wert der System Property bzw – falls diese noch nicht existiert hat – null zurück. Beispiel : System.setProperty("Labor.aktuell", "LSW"); • Ermittlung der System-Umgebung ◇ Properties werden in Objekten der Klasse Properties (Package java.util) gespeichert. Für die Standard System Properties wird beim Start der JVM ein entsprechendes Objekt angelegt. (SystemProperties-Objekt). Zu ihm kann über die Klasse System zugegriffen werden. Benutzerdefinierte System Properties (sowohl bei Programmstart festgelegte, als auch im Programm gesetzte) werden in dieses Objekt eingefügt. Ein Benutzer kann in einem Programm darüberhinaus weitere Properties-Objekte anlegen. ◇ Statische Methoden der Klasse System zum Zugriff zum System-Properties-Objekt : ▻ public static Properties getProperties() Funktionswert : das System-Properties-Objekt ▻ public static String getProperty(String key) Funktionswert : der Wert der System Property mit dem Namen key, bzw null, falls Property nicht existiert ◇ Sämtliche in einem Properties-Objekt enthaltenen Properties (Name/Wert-Paare) lassen sich mittels der folgenden Methode der Klasse Properties über ein PrintStream-Objekt ausgeben : public void list(PrintStream out); FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 333 – 00 – TH – 03 ------------------------------------------------------------------------------------ Interaktion mit dem Laufzeitsystem in Java (3) • Beispielprogramm zur Ausgabe der System Properties in die Standard-Ausgabe import java.util.Properties; class SysProps { public static void main(String[] args) { System.getProperties().list(System.out); } } -- listing properties -java.runtime.name=Java(TM) SE Runtime Environment sun.boot.library.path=C:\Programme\Java\jre1.6.0\bin java.vm.version=1.6.0-b105 java.vm.vendor=Sun Microsystems Inc. java.vendor.url=http://java.sun.com/ path.separator=; java.vm.name=Java HotSpot(TM) Client VM file.encoding.pkg=sun.io user.country=DE sun.java.launcher=SUN_STANDARD sun.os.patch.level=Service Pack 2 java.vm.specification.name=Java Virtual Machine Specification user.dir=E:\Java\Vorlesung\elemprogfunc java.runtime.version=1.6.0-b105 java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment java.endorsed.dirs=C:\Programme\Java\jre1.6.0\lib\endorsed os.arch=x86 java.io.tmpdir=C:\DOKUME~1\thomas\LOKALE~1\Temp\ line.separator= java.vm.specification.vendor=Sun Microsystems Inc. user.variant= os.name=Windows XP sun.jnu.encoding=Cp1252 java.library.path=C:\WINDOWS\system32;.;C:\WINDOWS\Sun\... java.specification.name=Java Platform API Specification java.class.version=50.0 sun.management.compiler=HotSpot Client Compiler os.version=5.1 user.home=C:\Dokumente und Einstellungen\thomas user.timezone= java.awt.printerjob=sun.awt.windows.WPrinterJob file.encoding=Cp1252 java.specification.version=1.6 user.name=thomas java.class.path=.;C:\Programme\Java\jre1.6.0\lib\ext\... java.vm.specification.version=1.0 sun.arch.data.model=32 java.home=C:\Programme\Java\jre1.6.0 java.specification.vendor=Sun Microsystems Inc. user.language=de awt.toolkit=sun.awt.windows.WToolkit java.vm.info=mixed mode, sharing java.version=1.6.0 java.ext.dirs=C:\Programme\Java\jre1.6.0\lib\ext;C:... sun.boot.class.path=C:\Programme\Java\jre1.6.0\lib\resour... java.vendor=Sun Microsystems Inc. file.separator=\ java.vendor.url.bug=http://java.sun.com/cgi-bin/bugreport... sun.cpu.endian=little sun.io.unicode.encoding=UnicodeLittle sun.desktop=windows sun.cpu.isalist= FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 334 – 00 – TH – 01 ----------------------------------------------------------------------------------- Interaktion mit dem Laufzeitsystem in Java (4) • Zugriff zu den Environment-Variablen des Betriebssystems ◇ Ab dem JDK 5.0 kann in Java-Programmen wieder zu den vom Betriebssystem verwalteten Environment-Variablen zugegriffen werden. ◇ Eine Environment-Variable besitzt – wie eine System Property – einen Namen und hat einen Wert. Sowohl Name als auch Wert sind jeweils ein String. Jede Environment-Variabale bildet ein String-Paar. ◇ Mit den folgenden statischen Methoden der Klasse System kann zu dem bei der Programmabarbeitung aktuellen Environment zugegriffen werden : ▻ public static Map<String, String> getenv() Ermittlung aller aktuellen Environment-Variablen. Funktionswert : - String-String-Map , die die Environment-Variablen enthält. Falls das Betriebssystem keine Environment-Variablen unterstützt, ist die zurückgegebene Map leer. Eine Map ist ein assoziativer Container, der Schlüssel (key) –Werte (value)-Paare speichert. Als Schlüssel dient hier der Name einer Environment-Variablen, der Wert ist der Wert dieser Variablen ▻ public static String getenv(String name) Ermittlung des Werts der Environment-Variablen mit dem Namen name Funktionswert : - Wert der Environment-Variablen - bzw null, wenn keine Environment-Variable mit dem Namen name existiert Falls ein Security Manager installiert ist, wird er von beiden Funktionen befragt, ob der Zugriff zum Environment zulässig ist. Bei Unzulässigkeit wird eine SecurityException geworfen. ◇ Beispielprogramm zum Zugriff zu den Environment-Variablen Auflistung aller Environmentvariablen (Name = Wert) in die Standard-Ausgabe // GetEnv.java // Ermittlung des aktuellen Environments import java.util.*; public class GetEnv { public static void main(String[] args) { Map<String, String> env = System.getenv(); Set<String> keys = env.keySet(); for (String name : keys) System.out.println(name + " = " + System.getenv(name)); } } FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 335 – 00 – TH – 01 ------------------------------------------------------------------------------------ Die Klasse Runtime in Java (1) • Grundsätzliches ◇ Die Klasse Runtime befindet sich im Package java.lang. ◇ Jede Java-Applikation besitzt genau ein Objekt dieser Klasse. Es wird beim Start der JVM automatisch erzeugt. Dieses Objekt bildet ein Interface zwischen der Java-Applikation und der Laufzeitumgebung der ausführenden JVM. ◇ Zur Ermittlung des aktuellen Runtime-Objekts dient die statischen Methode der Klasse Runtime : static Runtime getRuntime() Runtime.getRuntime() liefert das mit der aktuellen Java-Applikation assoziierte Runtime-Objekt. ◇ Eine explizite Instanzierung der Klasse ist nicht möglich. ◇ Die Klasse Runtime stellt Funktionalitäten in folgenden Bereichen zur Verfügung : ▻ Information über Systemresourcem der JVM (Prozessoranzahl, Arbeitsspeicher) ▻ expliziter Aufruf des Garbage Collectors ▻ Ausführung externer Programme in Kindprozessen ▻ Laden dynamischer Bibliotheken (nativer Code) ▻ Debug-Unterstützung ▻ Beendigung (shutdown) der JVM • Information über Systemresourcen der JVM ◇ Hierfür dienen die folgenden Methoden der Klasse Runtime public int availableProcessors() Rückgabe der Anzahl Prozessoren, die der JVM zur Verfügung stehen public long freeMemory() Ermittlung des freien der JVM zur Verfügung stehenden Arbeitsspeichers, Funktionswert = freier Arbeitsspeicher in Bytes public long totalMemory() Ermittlung des gesamten der JVM zur Verfügung stehenden Arbeitspeichers, Funktionswert = gesamter Arbeitsspeicher in Bytes public long maxMemory() Ermittlung der maximalen Arbeitspeichergröße, die die JVM zu nutzen versuchen wird (in Bytes) Falls keine obere Grenze existiert, Rückgabe von Long.MAX_VALUE ◇ Demonstrationsbeispiel : public class ResInfo { public static void main(String[] args) { Runtime rt = Runtime.getRuntime(); System.out.println("Einige Systemresourcen der JVM :"); System.out.println("Anzahl Prozessoren : " + rt.availableProcessors()); System.out.println("gesamter Arbeitsspeicher : " + rt.totalMemory() + " Bytes"); System.out.println("freier Arbeitsspeicher : " + rt.freeMemory() + " Bytes"); System.out.println("maximaler Arbeitsspeicher : " + rt.maxMemory() + " Bytes"); } } Einige Systemresourcen der JVM : Anzahl Prozessoren : 2 gesamter Arbeitsspeicher : 5177344 Bytes freier Arbeitsspeicher : 4997096 Bytes maximaler Arbeitsspeicher : 66650112 Bytes FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 336 – 00 – TH – 02 ------------------------------------------------------------------------------------ Die Klasse Runtime in Java (2) • Ausführung externer Programme in Kindprozessen ◇ Die Erzeugung von Kindprozessen, die ein anzugebendes Programm ausführen, wird durch mehrere überladene Methoden mit dem Namen exec ermöglicht. ◇ Alle exec-Methoden geben bei Erfolg als Funktionswert ein Objekt der Klasse Process zurück. Dieses Objekt repräsentiert den neu erzeugten Kindprozeß. Es ermöglicht dem Elternprozeß hinsichtlich bestimmter Aspekte eine Interaktion mit dem erzeugten Kindprozeß (z.B. Warten auf Kindprozeßende, Ermittlung des ReturnCodes des Kindprozesses, Abbruch des Kindprozesses) ◇ Beim Auftreten von Fehlern werfen die exec-Methoden entsprechende Exceptions. So werfen alle exec-Methoden beim Auftreten eines I/O-Fehlers (z.B. Programmdatei nicht gefunden) eine IOException. ◇ Falls ein Security Manager installiert ist (ein SecurityManager-Objekt existiert), überprüft dieser, ob die Ausführung des angegebenen Programms zulässig ist. Bei Unzulässigkeit wird eine SecurityException geworfen. ◇ Überblick über die exec-Methoden (Auswahl) : public Process exec(String cmd) throws IOException Ausführung des durch cmd referierten Programms in einem neu erzeugten Kindprozeß public Process exec(String[] cmdarr) Ausführung des durch cmdarr[0] referierten Programms in einem throws IOException neu erzeugten Kindprozeß. Die übrigen Elemente von cmdarr (ab Index 1) werden dem Programm als Programmparameter übergeben public Process exec(String cmd, String[] envp) throws IOException Ausführung des durch cmd referierten Programms in einem neu erzeugten Kindprozeß envp referiert das dem Programm zu übergebende Environment public Process exec(String[] cmdarr, Ausführung des durch cmdarr[0] referierten Programms in einem String[] envp) neu erzeugten Kindprozeß. Die übrigen Elemente von cmdarr throws IOException (ab Index 1) werden dem Programm als Programmparameter übergeben envp referiert das dem Programm zu übergebende Environment Wird kein Environment angegeben (Methoden mit nur einem Parameter bzw envp == null) so wird dem im Kindprozess ausgeführten Programm das Environment des Elternprozesses übergeben Es existieren zwei weitere exec-Methoden (3 Parameter), mit denen für den neu erzeugten Kindprozeß explizit das Arbeitsdirectory festgelegt werden kann. Wird für den entsprechenden Parameter null übergeben so erbt – wie bei den o.a. exec-Methoden – der Kindprozeß das Arbeitsdirectory des Elternprozesses. ◇ Einfaches Demonstrationsbeispiel : import java.io.*; class ExecDemo { public static void main(String[] args) throws IOException { String[] cmd = null; if (args.length>0) cmd = args; else { cmd = new String[1]; cmd[0]= "calc"; } Runtime.getRuntime().exec(cmd); } } FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 341 – 00 – TH – 03 ----------------------------------------------------------------------------------- Exceptions in Java (1) • Prinzip des Exception Handlings ◇ Java stellt – wie auch C++ – einen speziellen Mechanismus zur Behandlung von Ausnahmesituationen (Fehlerfällen, Exceptions), die während der Programmausführung auftreten können, zur Verfügung ⇒ Exception Handling ◇ Ausnahmesituationen in diesem Sinne sind Fehler, oder sonstige unerwünschte Sonderfälle (z.B. Dateizugriffsfehler, Verletzung von Array-Grenzen, Datenformatfehler usw), die im normalen Programmablauf nicht auftreten sollten, aber auftreten können. Exception Handling ist kein Mechanismus zur Behandlung von externen oder internen Interrupts. ◇ Exception Handling trennt den Code, der Fehler verursachen kann, von dem Code, der einen aufgetretenen Fehler behandelt. Dadurch kann der eigentliche den normalen Programmablauf steuernde (produktive) Code frei gehalten werden von einer ständigen Überprüfung auf den Auftritt von Fehlern und Sonderfällen sowie der Reaktion auf diese. Dies trägt erheblich zur Klarheit und Übersichtlichkeit des Codes bei. ◇ Code (z.B. eine Methode einer Bibliotheksklasse), der eine Ausnahmesituation entdeckt, wirft eine Exception, die dann von einem anderen Code-Teil, dem Exception-Handler gefangen wird. Im Exception-Handler findet die Reaktion auf die (Bearbeitung der) Ausnahmesituation statt. Diese kann der Fehlerart sowie der jeweiligen spezifischen Programmsituation angepasst werden. Z.B. kann eine Fehlermeldung ausgegeben werden und anschliessend das Programm fortgesetzt oder beendet werden. Oder es kann versucht werden, die Fehlerursache zu beseitigen und das Programm dann fortzusetzen. ◇ Exceptions werden als Objekte behandelt. Sie enthalten Informationen über die Fehlerursache und stellen Methoden zum Zugriff zu diesen zur Verfügung. Werfen einer Exception (throwing) bedeutet das Erzeugen eines Objekts einer Exception-Klasse und die anschliessende Suche eines passenden Exception-Handlers. Wird ein derartiger Handler gefunden, wird ihm das Exception-Objekt (genauer eine Referenz darauf) übergeben ( Fangen der Exception, catching). Dem Handler stehen damit die im Exception-Objekt enthaltenen Informationen zur Auswertung zur Verfügung. ◇ Exception Handling wird in Java wesentlich umfangreicher und strikter als in C++ angewendet : ▻ In der Standard-Bibliothek sind zahlreiche Exception-Klassen definiert. Sie bilden eine über mehrere Pakete verteilte Klassenhierarchie, die die Klasse Throwable (von Object abgeleitet, Paket java.lang) als Wurzelklasse besitzt. Im Konstruktor einer derartigen Klasse wird i.a. die Exception-Ursache bzw eine Kurzbeschreibung der Exception durch einen String (fest codiert oder als Parameter übergeben) festgelegt. ▻ Viele Methoden vieler Bibliotheksklassen werfen Exceptions. ▻ Java erzwingt, dass geworfene Exceptions gefangen werden müssen. Existiert in einem Benutzerprogramm kein geeigneter Exception-Handler, so werden sie von einem in der JVM angesiedelten Standard-Handler behandelt, der Informationen über die Exception in die Standard-Ausgabe ausgibt und anschliessend das Programm (genauer den aktuellen Thread) beendet. ▻ Ein Benutzer kann jederzeit eigene Exception-Klassen definieren. Dies kann sinnvoll sein, wenn spezielle Fehlerfälle gesondert von anderen behandelt werden sollen (z.B. "Division durch Null" als Spezialfall einer ArithmeticException). Eine beutzerdefinierte Exception-Klasse muß von einer der Standard-Bibliotheks-Exception-Klassen abgeleitet sein FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK BEREICH DATENTECHNIK V – JV – 342 – 00 – TH – 03 ----------------------------------------------------------------------------------- Exceptions in Java (2) • Hierarchie der Bibliotheks-Exception-Klassen ◇ Alle Exception-Klassen sind – direkt oder indirekt – von der Klasse Throwable abgeleitet. ◇ Die Klasse Throwable (Paket java.lang) ist eine direkte Unterklasse von Object. ◇ Überblick über den Anfang der Hierarchie : Throwable Error VirtualMachineError weitere Error-Klassen ArithmeticException Exception RuntimeException IOException weitere RuntimeExceptionKlassen FileNotFoundException weitere ExceptionKlassen weitere IOExceptionKlassen ◇ Exceptions der Klasse Error sowie der davon abgeleiteten Klassen kennzeichnen ernsthafte Systemfehler, die normalerweise nicht auftreten sollten, aber prinzipiell jederzeit auftreten können. Ein normales Benutzerprogramm kann auf derartige Exceptions i.a. nicht sinnvoll reagieren und sollte sie deswegen auch nicht fangen. Vielmehr sollten sie immer vom Default-Exception-Handler der JVM behandelt werden. ◇ Exceptions der Klasse RuntimeException sowie der davon abgeleiteten Klassen können ebenfalls prinzipiell an beliebiger Stelle während des Programmablaufs auftreten. I.a. liegt ihre Ursache in einem logischen Programmierfehler (z.B. Division durch 0 oder unzulässiger Array-Index). Eine vernünftige Reaktion zur Laufzeit ist i.a. nicht möglich. Derartige Fehler sollten i.a. im Programm-Code korrigiert werden. Ein Benutzerprogramm kann diese Exceptions behandeln (d.h. geeignete Exception-Handler bereitstellen), muß es aber nicht. Im letzteren Fall erfolgt wiederum eine Behandlung durch den Default-Handler der JVM. ◇ Exceptions aller übrigen Klassen (z.B. IOException) repräsentieren Fehler, mit denen man prinzipiell rechnen muß (z.B. Datei ist nicht vorhanden) und die deswegen auch in irgendeiner Weise behandelt werden müssen. Für diese Exceptions schreibt Java eine "catch-or-declare"-Erfordernis vor. Sie müssen von der Funktion, in der sie geworfen werden, entweder gefangen oder von ihr als weiter-werfbar deklariert werden. Andererseits darf eine Funktion nur solche Exceptions dieser Klassen werfen, die sie auch deklariert hat. Das Einhalten dieser Erfordernis kann vom Compiler überprüft werden. Sie werden daher als geprüfte (checked) Exceptions bezeichnet. ◇ Exceptions der Klassen Error und RuntimeException sowie der davon abgeleiteten Klassen sind dagegen ungeprüfte (unchecked) Exceptions. Sie können jederzeit geworfen werden, ohne daß sie von der entsprechenden Funktion deklariert werden müssen. Für sie gilt die "catch-or-declare"-Erfordernis nicht, sie dürfen aber deklariert werden FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 343 – 00 – TH – 02 ----------------------------------------------------------------------------------- Exceptions in Java (3) • Die Klasse Throwable ◇ Die direkt von der Klasse Object abgeleitete Klasse Throwable (Paket java.lang) ist Basisklasse aller Exception-Klassen. ◇ Sie definiert ein allgemeines Interface für den Zugriff zu den Exception-Objekten aller Exception-Klassen Die vier wichtigsten Methoden dieses Interfaces sind : ▻ public String getMessage(); Diese Methode gibt den bei der Exception-Objekt-Erzeugung gespeicherten Ursachen- bzw KurzbeschreibungsString als Funktionswert zurück, bzw null, falls kein derartiger String gespeichert wurde. ▻ public String toString(); Diese Methode erzeugt einen String, der aus dem vollqualifizierten Namen der tatsächlichen Klasse des ExceptionObjekts besteht, gegebenenfalls (falls getMessage() einen Wert !=null zurückgibt) gefolgt von ": " und dem Rückgabewert von getMessage(). ▻ public void printStackTrace(); Diese Methode gibt den Funktionswert von toString() gefolgt von dem Aufruf-Stack der Funktion, in der die Exception ursprünglich geworfen wurde, in die Standard-Fehler-Ausgabe (System.err) aus. ▻ public void printStackTrace(PrintStream s); Diese Methode gibt den Funktionswert von toString() gefolgt von dem Aufruf-Stack der Funktion, in der die Exception ursprünglich geworfen wurde, in den durch s referierten Print-Stream aus. • Deklaration werfbarer Exceptions (throws-Klausel) ◇ Die von einer Funktion werfbaren geprüften Exceptions müssen von dieser deklariert werden. Werfbare ungeprüfte Exceptions können, müssen aber nicht deklariert werden. ◇ Die Deklaration erfolgt durch eine im Funktionskopf nach der Parameterliste anzugebende throws-Klausel. Die throws-Klausel besteht aus dem Schlüsselwort throws, gefolgt von einer durch Kommata getrennten Auflistung von Exception-Klassen ◇ Syntax : throws Exception-Klasse , ◇ Beispiel : public String liesEtwas(String dname) throws FileNotFoundException, EOFException { // ... } • Werfen einer Exception ◇ Mittels einer throw-Anweisung. Nach dem Schlüsselwort throw ist eine Referenz auf das zu werfende Exception-Objekt anzugeben. Diese Referenz kann ▻ der Wert eines new-Ausdrucks sein (neu erzeugtes Exception-Objekt) ▻ die einem Exception-Handler übergebene Objekt-Referenz sein ("Weiterwerfen" der Exception) ◇ Syntax : ◇ Beispiel : throw Exception-Objekt-Referenz ; throw new ArithmeticException("Nenner ist Null"); FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 344 – 00 – TH – 02 ------------------------------------------------------------------------------------ Exceptions in Java (4) • Die try-Anweisung ◇ Sie ermöglicht das Fangen von Exceptions. ◇ Eine try-Anweisung besteht i.a. aus drei Teilen : ▻ dem try-Block ▻ einem oder mehreren catch-Blöcken ▻ einem finally-Block Entweder die catch-Blöcke oder der finally-Block dürfen auch fehlen, aber nicht beides. ◇ Syntax : try { catch ( finally Anweisung Exception-Klasse } Name { Anweisung } { Anweisung } ) ◇ Der try-Block enthält den eigentlichen produktiven Code, der auf den Auftritt von Exceptions überwacht wird. Er wird solange ausgeführt, bis entweder durch eine der Anweisungen eine Exception (direkt durch eine throw-Anweisung oder indirekt durch eine aufgerufene Funktion) geworfen wird oder alle Anweisungen erfolgreich abgearbeitet worden sind. Beim Auftritt einer Exception wird der try-Block sofort verlassen und nach einem Exception-Handler gesucht, der die Exception fangen kann. ◇ Die catch-Blöcke bilden die Exception-Handler. Jeder catch-Block ist zuständig für das Fangen von Exceptions einer bestimmten Klasse bzw deren Unterklassen. Die von einem catch-Block fangbare Exception-Klasse ist in seinem Kopf – analog zur Parameter-Deklaration von Funktionen – angegeben. Da Objekte (genauer Objekt-Referenzen) einer Klasse zuweisungskompatibel zu Variablen einer Basisklasse sind, können auch Exceptions aller Klassen, die von der deklarierten Klasse abgeleitet sind, gefangen werden. Die Suche nach einem "passenden" Exception-Handler erfolgt in der Reihenfolge ihrer Angabe im Quellcode. Wird ein Exception-Handler gefunden, der die geworfene Exception fangen kann, wird das Programm mit seiner Abarbeitung fortgesetzt. Dabei wird die Exception wie ein formaler Funktionsparameter an den Handler übergeben. Wird kein "passender" Exception-Handler gefunden, wird die Suche in der jeweils nächsten umfassenden try-Anweisung (gegebenenfalls in der aufrufenden Funktion) fortgesetzt. Bleibt auch das erfolglos, wird der Default-Exception-Handler der JVM ausgeführt und das Programm beendet. ◇ Der finally-Block enthält Code, der immer ausgeführt wird, unabhängig davon, wie die try-Anweisung verlassen wird, ob durch reguläre Beendigung des try-Blocks oder durch Werfen einer gefangenen oder nicht gefangenen Exception. Die Ausführung des finally-Blocks erfolgt unmittelbar vor Verlassen des try-Blocks bzw – beim Fangen einer Exception – vor Verlassen des entsprechenden catch-Blocks. Die Ausführung erfolgt auch dann, wenn try- bzw catch-Block mit einer return-Anweisung verlassen werden. Der finally-Block wird insbesondere verwendet, um Aufräumarbeiten durchzuführen und sicherzustellen, dass belegte System-Resourcen (z.B. geöffnete Dateien) freigegeben werden FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK BEREICH DATENTECHNIK V – JV – 345 – 00 – TH – 01 ----------------------------------------------------------------------------------- Exceptions in Java (5) • Demonstrationsprogramm zu Exceptions // ExceptDemo.java import java.io.*; class ExceptDemo { public void func1() { try { System.out.println("in func1() : Aufruf von func2()"); func2(); System.out.println("normales Ende von try in func1()!"); return; } finally { System.out.println("func1() verlassen !"); } } public void func2() { try { System.out.println("in func2() : Aufruf von func3()"); func3(); System.out.println("normales Ende von try in func2()!"); return; } catch (RuntimeException e) { System.out.print("Exception-Handler in func2() : "); System.out.println(e.getMessage()); } finally { System.out.println("func2() verlassen !"); } } public void func3() { try { System.out.println("in func3() : Exception wird geworfen"); throw new RuntimeException("Demo-Exception !"); } catch (ArithmeticException e) { System.out.print("Exception-Handler in func3() : "); System.out.println(e.getMessage()); } finally { System.out.println("func3() verlassen !"); } } public static void main(String[] args) { ExceptDemo ed = new ExceptDemo(); ed.func1(); } } in func1() : Aufruf von func2() in func2() : Aufruf von func3() in func3() : Exception wird geworfen func3() verlassen ! Exception-Handler in func2() : Demo-Exception ! func2() verlassen ! normales Ende von try in func1()! func1() verlassen ! FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK BEREICH DATENTECHNIK V – JV – 351 – 00 – TH – 01 ----------------------------------------------------------------------------------- Dateizugriff in Java (1) • Überblick ◇ Java behandelt Dateien als sequentielle Folge von Bytes (Byte-Streams) ◇ In der IO-Bibliothek (Package java.io) sind zahlreiche Klassen definiert, die das Arbeiten mit Dateien unterstützen. Die wichtigsten dieser Klassen sind : ▻ die File-Stream-Klassen zum sequentiellen Zugriff • FileInputStream (byteweises Lesen) • FileOutputStream (byteweises Schreiben) • FileReader (zeichenweises Lesen) • FileWriter (zeichenweises Schreiben) ▻ eine Klasse zum wahlfreien Zugriff (Lesen und Schreiben) • RandomAccessFile ▻ Klassen für den Zugriff zum Dateisystem • FileDescriptor • File ◇ Auszugsweises Klassendiagramm : Anmerkungen : ▻ Das Diagramm beschränkt sich auf die Datei-Eingabe-Stream-Klassen (FileInputStream, FileReader). ▻ Für die Datei-Ausgabe-Stream-Klassen (FileOutputStream, FileWriter) bestehen analoge Ableitungsund Nutzungsbeziehungen. Deren – direkte oder indirekte – Basisklassen sind OutputStream bzw Writer. ▻ Die IO-Bibliothek enthält eine Reihe weiterer – hier nicht aufgeführter – Streamklassen, die zumeist von InputStream oder Reader (bzw OutputStream oder Writer) direkt oder indirekt abgeleitet sind. InputStream Reader FilterInputStream BufferedInputStream DataInputStream InputStreamReader FileInputStream FileReader FileDescriptor File BufferedReader RandomAccessFile FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 352 – 01 – TH – 04 ------------------------------------------------------------------------------------ Dateizugriff in Java (2-1) • Die Klasse File ◇ Objekte dieser Klasse repräsentieren Zugriffspfade (zu Dateien bzw Directories) im Dateisystem. ◇ Wesentliche Funktionalitäten : ▻ Speicherung eines Datei- bzw Directory-Zugriffspfades in einer abstrakten system-unabhängigen Darstellung, sowie Bereitstellung von Informationen über denselben ▻ Ermittlung diverser Eigenschaften einer repräsentierten Datei (bzw eines repräsentierten Directories) ▻ Manipulation von Dateisystem-Einträgen (Erzeugen, Löschen, Änderung bestimmter Eigenschaften) ◇ Der repräsentierte Zugriffspfad kann durch einen absoluten oder einen relativen Pfadnamen bezeichnet sein. Ein relativer Pfadname wird immer auf das aktuelle Arbeitsdirectory des Users bezogen (Wert der System Property user.dir). Typischerweise handelt es sich hierbei um das Directory, aus dem die JVM gestartet wurde. ◇ Zugriffspfade bestehen aus : ▻ einem optionalen betriebsystem-abhängigen Prefix-String (z.B. "D:\\", "E:" oder "/") ▻ einer Folge von keinem oder mehr Namen-Strings, die jeweils ein Directory bzw (nur der letzte String) eine Datei bezeichnen. Die einzelnen Namen-Strings sind durch ein betriebssystem-abhängiges Trennzeichen separiert. Das betriebssystem-abhängige Trennzeichen ist der Wert der System Property file.separator. Es steht auch als öffentliche statische Datenkomponente der Klasse File zur Verfügung : public static final char separatorChar; bzw public static final String separator; (String mit einem Zeichen) ◇ Konstruktoren : ▻ public File(String path) Erzeugung eines neuen File-Objekts, das den Zugriffspfad path repräsentiert. Falls path==null ist, wird eine NullPointerException geworfen. ▻ public File(String dirName, String name) Erzeugung eines neuen File-Objekts, das den aus dirName und name gebildeten Zugriffspfad repräsentiert. (Eintrag name im Directory dirName). Äquivalent zu : File(dirName + File.separator + name) Falls name==null ist, wird eine NullPointerException geworfen. ▻ public File(File fileDir, String name) Erzeugung eines neuen File-Objekts, das den Zugriffspfad repräsentiert, der aus dem Eintrag name in dem durch fileDir repräsentierten Directory gebildet wird, Äquivalent zu : File(fileDir.getPath(), name) Falls name==null ist, wird eine NullPointerException geworfen. ▻ public File(URI uri) Erzeugung eines neuen File-Objekts, dessen repräsentierter Zugriffspfad durch Konvertierung des Unified Resource Identifiers erhalten wird, der durch das URI-Objekt uri repräsentiert wird. Es muß sich hierbei um den Resource Identifier einer Datei handeln (Beginn mit file:) Falls uri==null ist, wird eine NullPointerException geworfen. Falls uri keine Datei repräsentiert, wird eine IllegalArgumentException geworfen. ◇ Der durch ein File-Objekt repräsentierte Zugriffspfad muß nicht einen tatsächlich existierenden Dateisystem-Eintrag referieren. Zur Überprüfung, ob ein entsprechender Dateisystem-Eintrag vorhanden ist, d.h. durch das File-Objekt also tatsächlich eine Datei oder ein Directory repräsentiert wird, dient die Memberfunktion ▻ public boolean exists() Funktionswert : true, wenn der Eintrag existiert, false, wenn der Eintrag nicht existiert FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 352 – 02 – TH – 03 ------------------------------------------------------------------------------------ Dateizugriff in Java (2-2) • Die Klasse File, Forts. ◇ Methoden zum Erzeugen neuer Dateisystem-Einträge ▻ public boolean createNewFile() throws IOException Diese Methode erzeugt eine neue leere Datei mit dem vom aktuellen File-Objekt repräsentierten Zugriffspfad, falls noch keine Datei mit diesem Zugriffspfad existiert. Funktionswert : true, falls die Datei erzeugt werden konnte false, falls eine Datei mit dem Zugriffspfad bereits existiert hat. Falls ein I/O-Fehler auftritt, wird eine IOException geworfen. ▻ public boolean mkdir() Diese Methode erzeugt eine neues Directory mit dem vom aktuellen File-Objekt repräsentierten Zugriffspfad Funktionswert : true, falls das Directory erzeugt werden konnte, andernfalls false ▻ public boolean mkdirs() Diese Methode erzeugt ein neues Directory mit dem vom aktuellen File-Objekt repräsentierten Zugriffspfad sowie gegebenenfalls alle noch nicht existierenden Eltern-Directories. Funktionswert : true, falls das Directory und alle noch nicht existierenden Eltern-Directories erzeugt werden konnten false, falls das Directory nicht erzeugt werden konnte. Anm. : In diesem Fall können durchaus einige Eltern-Directories erzeugt worden sein. ◇ Methoden zur Ermittlung von Informationen über Dateisystem-Einträge ▻ public String getAbsolutePath() Rückgabe des absoluten Pfadnamens ▻ public String getCanonicalPath() Rückgabe des kanonischen Pfadnamens ▻ public long length() Rückgabe der Dateilänge, bei Directories undefinierter Funktionswert ▻ public boolean isDirectory() true, wenn Eintrag existiert und Directory ist, sonst false ▻ public boolean isFile() true, wenn Eintrag existiert und normale Datei ist, sonst false ▻ public boolean isHidden() true, wenn Eintrag existiert und verborgen ist, sonst false ▻ public boolean canWrite() true, wenn Eintrag existiert und geändert werden kann, sonst false ▻ public boolean canRead() true, wenn Eintrag existiert und gelesen werden kann, sonst false ▻ public String[] list() Wenn Eintrag ein Directory ist : Rückgabe einer Auflistung aller in ihm enthaltenen Einträge als String-Array (ausser "." und "..") Wenn Eintrag kein Directory ist : Rückgabe von null ▻ public File[] listFiles() Wie list(), nur Rückgabe der Einträge als File-Array ◇ Methoden zur Veränderung von Dateisystem-Einträgen ▻ public boolean renameTo(File newPath) Umbenennen / Verschieben des aktuell repräsentierten Dateisystem-Eintrags. Der Dateisystem-Eintrag wird anschliessend durch das File-Objekt newPath repräsentiert. Der vom aktuellen Objekt bisher repräsentierte Eintrag existiert anschliessend nicht mehr. Funktionswert : true, falls Umbenennen / Verschieben erfolgreich war, andernfalls false Falls newPath==null ist, wird eine NullPointerException geworfen. ▻ public boolean delete() Löschen des aktuell repräsentierten Dateisystem-Eintrags. Ein zu löschendes Directory muss es leer sein. Funktionswert : true, falls erfolgreich gelöscht werden konnte, andernfalls false ◇ Es existieren noch zahlreiche weiterer Methoden. ◇ Alle Methoden, die zu einer System Property zugreifen oder einen Zugriff zum Dateisystem bewirken, werfen eine SecurityException, wenn der Zugriff nicht zulässig ist. FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK BEREICH DATENTECHNIK V – JV – 352 – 03 – TH – 01 ----------------------------------------------------------------------------------- Dateizugriff in Java (2-3) • Demoprogramm 1 zur Klasse File // TestRename.java import java.io.*; public class TestRename { public static void main(String[] args) throws IOException { if (args.length<=1) System.out.println("Angabe von Quell- und Zielpfad erforderlich"); else { File fil = new File(args[0]); if (!fil.exists()) { System.out.print("Quellpfad \"" + args[0] + "\" existiert nicht"); if (fil.createNewFile()) System.out.println(" --> neu erzeugt"); else System.out.println(" --> Erzeugung nicht möglich"); } if (fil.exists()) { System.out.println("Dateigroesse : " + fil.length() + " Bytes"); File neufil = new File(args[1]); boolean succ = fil.renameTo(neufil); if (!succ) System.out.println("rename nicht erfolgreich"); else { System.out.println("rename erfolgreich"); System.out.print("alter Pfad : " + fil); if (!fil.exists()) System.out.println(" existiert nicht mehr"); System.out.println("neuer Pfad : " + neufil); } } } } Beispiele für Programmaufruf und -ausgabe E:\Java\fhm\ee\vorl\fileacc>java TestRename ftest2.txt ftest2.dat Dateigroesse : 33 Bytes rename erfolgreich alter Pfad : ftest2.txt existiert nicht mehr neuer Pfad : ftest2.dat E:\Java\fhm\ee\vorl\fileacc>java TestRename ftest2.txt ftest2.dat Quellpfad "ftest2.txt" existiert nicht --> neu erzeugt Dateigroesse : 0 Bytes rename nicht erfolgreich FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 352 – 04 – TH – 03 ------------------------------------------------------------------------------------ Dateizugriff in Java (2-4) • Demoprogramm 2 zur Klasse File // ListDir.java import java.io.*; public class ListDir { public static void main(String[] args) { try { if (args.length<=0) throw new IOException("Programmparameter (Directory-Pfad) fehlt !"); File dir = new File(args[0]); if (!dir.exists()) throw new IOException("\"" + args[0] + "\" existiert nicht !"); if (!dir.isDirectory()) throw new IOException("\"" + dir.getAbsolutePath() + "\" ist kein Directory!"); String[] entries = dir.list(); System.out.println("Inhalt des Directories \"" + dir.getAbsolutePath() + "\" :"); for (int i=0; i<entries.length; i++) System.out.println(entries[i]); } catch (IOException ex) { System.out.println(ex.getMessage()); } } } Beispiele für Programmaufruf und -ausgabe E:\Java\fhm\ee\vorl\fileacc>java ListDir Programmparameter (Directory-Pfad) fehlt ! E:\Java\fhm\ee\vorl\fileacc>java ListDir meindir "meindir" existiert nicht ! E:\Java\fhm\ee\vorl\fileacc>java ListDir ftestdir "E:\Java\fhm\ee\vorl\fileacc\ftestdir" ist kein Directory! E:\Java\fhm\ee\vorl\fileacc>java ListDir . Inhalt des Directories "E:\Java\fhm\ee\vorl\fileacc\." : FileTest1.java FileTest1.class ftest.txt ftest2.dat TestRename.java TestRename.class ftest1.dat ftest3.txt testren1.txt testren2.txt ftestdir ListDir.java ListDir.class FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 353 – 00 – TH – 04 ------------------------------------------------------------------------------------ Dateizugriff in Java (3) • Die Klasse FileDescriptor ◇ Objekte dieser Klasse bilden ein Handle zu der vom jeweiligen Betriebssystem für eine geöffnete Datei (allgemeiner : für einen geöffneten Stream) angelegten Verwaltungsstruktur. ◇ Jedes Objekt, über dem ein Zugriff zu einer Datei erfolgt (Objekt einer File-Stream-Klasse bzw der Klasse RandomAccessFile) ist mit einem FileDescriptor-Objekt assoziiert. Dieses stellt die Verbindung zur Dateiverwaltung auf der Betriebssystemebene her. ◇ Ein FileDescriptor-Objekt wird üblicherweise implizit beim Anlegen eines Objekts für den Dateizugriff und dem damit verbundenen Öffnen der Datei erzeugt. Ein explizites Erzeugen eines FileDescriptor-Objekts ist weder üblich noch sinnvoll. Mit dem zur Verfügung stehenden öffentlichen parameterlosen Konstruktor kann nur ein ungültiges Objekt, das an keine geöffnete Datei gebunden ist, erzeugt werden. ◇ Für Objekte der Klassen FileInputStream, FileOutputStream und RandomAccessFile (nicht jedoch der Klassen FileReader und FileWriter) kann mit der jeweiligen Methode getFD() das mit ihnen assoziierte FileDescriptor-Objekt ermittelt werden. ◇ Bei der Erzeugung eines neuen File-Stream-Objekts kann auch ein existierendes FileDescriptor-Objekt verwendet werden. Das neue File-Stream-Objekt referiert dann dieselbe Datei wie das File-Stream-Objekt, das das FileDescriptor-Objekt geliefert hat. Damit kann über zwei (oder mehr) Stream-Objekte zur selben Datei zugegriffen werden. ◇ Methoden der Klasse FileDescriptor ▻ public boolean valid() Überprüfung, ob das FileDescriptor-Objekt gültig, d.h. an eine geöffnete Datei gebunden ist. Funktionswert : true, falls das Objekt an eine geöffnete Datei gebunden ist, andernfalls false ▻ public void sync() throws SyncFailedException Synchronisation aller System-Buffer, die Daten für die referierte Datei enthalten, mit dem physikalischen Speichermedium. Die Funktion kehrt erst dann zurück, wenn alle relevanten Daten auf das physikalische Medium geschrieben worden sind. Die Methode sorgt nicht für das Herausschreiben von Buffern, die in dem Anwendungsprogramm verwendet werden (z.B. von einem BufferedOutputStream-Objekt). Diese müssen gegebenenfalls zuvor an das Betriebssystem übergeben werden (mittels der jeweiligen Stream-Methode flush()). Wenn eine Synchronisation der System-Buffer mit dem physikalischen Speichermedium nicht sichergestellt werden kann, wird eine SyncFailedException geworfen. ◇ Die Klasse FileDscriptor stellt Handle zu den Standard-Streams als öffentliche statische Datenkomponenten zur Verfügung Normalerweise werden diese jedoch nicht direkt von User-Code verwendet sondern indirekt über die durch die Klasse System bereitgestellten Standard-Stream-Objekte. ▻ public static final FileDescriptor in Handle zum Standard-Eingabe-Stream ▻ public static final FileDescriptor out Handle zum Standard-Ausgabe-Stream ▻ public static final FileDescriptor err Handle zum Standard-Fehlerausgab-Stream FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 354 – 01 – TH – 04 ------------------------------------------------------------------------------------ Dateizugriff in Java (4-1) • Die File-Stream-Klassen ◇ Objekte dieser Klassen ermöglichen einen sequentiellen Zugriff zu Dateien : ▻ FileInputStream (byteweises Lesen) ▻ FileOutputStream (byteweises Schreiben) ▻ FileReader (zeichenweises Lesen) ▻ FileWriter (zeichenweises Schreiben) ◇ Überblick über die Konstruktoren : 1.Parameter 2. Parameter String path Dateizugriffspfad File fil repräsentiert Dateizugriffspfad ------- existiert für Klasse FileInputStream FileOutputStream FileReader FileWriter FileDescriptor fd referiert geöffnete Datei String path Dateizugriffspfad File fil repräsentiert Dateizugriffspfad Beispiel : boolean app wenn true : Anhängen an Datei (append) wenn false : Schreiben am Dateianfang FileOutputStream FileWriter public FileInputStream(File datei) throws FileNotFoundException ● Bei der Erzeugung eines File-Stream-Objekts für einen Dateizugriffspfad (Param. vom Typ String bzw. File) ▻ wird die referierte Datei – falls sie vorhanden und die jeweilige Zugriffsart zulässig ist – geöffnet ▻ und ein an sie gebundenes FileDescriptor-Objekt erzeugt. Die Konstruktoren der Datei-Ausgabe-Stream-Klassen versuchen die referierte Datei neu anzulegen, falls sie nicht existiert. Kann eine Datei nicht geöffnet werden (z.B. weil der Zugriffspfad ein Directory referiert), wird eine FileNotFoundException geworfen. ● Bei der Erzeugung eines File-Stream-Objekts für eine bereits geöffnete Datei (Parameter vom Typ FileDescriptor) ▻ wird zu der Datei – falls die jeweilige Zugriffsart zulässig ist – ein weiterer Zugriffskanal geöffnet ● Alle Konstruktoren werfen eine SecurityException, wenn ein SecurityManager-Objekt existiert und dieser feststellt, dass die jeweilige Zugriffsart nicht zulässig ist. ◇ Schliessen eines File-Streams mittels der für alle File-Stream-Klassen existierenden Methode ▻ public void close() throws IOException Die Methode schliesst den File-Stream und damit die referierte Datei und gibt alle sonstigen mit dem Stream assoziierten System-Resourcen frei. Beim Auftritt eines I/O-Fehlers wird eine IOException geworfen. FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 354 – 02 – TH – 05 ------------------------------------------------------------------------------------ Dateizugriff in Java (4-2) • Die File-Stream-Klassen, Forts. ◇ Ermittlung des assoziierten FileDescriptor-Objekts Dies ist nur für die Klassen FileInputStream und FileOutputStream möglich. Für diese Klassen existiert die Methode ▻ public final FileDescriptor getFD() throws IOException Die Methode gibt das mit dem Stream-Objekt assoziierte FileDescriptor-Objekt zurück. Beim Auftritt eines I/O-Fehlers wird eine IOException geworfen. ◇ Methoden zum Dateizugriff Die File-Stream-Klassen stellen das von ihrer jeweiligen Basisklasse definierte Stream-Zugriffs-Interface zur Verfügung. Die wichtigsten Methoden dieser Interfaces sind : Methode Wirkung existiert für Klasse void write(int b) void write(byte[] buff) void write(byte[] buff, int pos, int len) Schreiben des Bytes b Schreiben des Byte-Buffers buff Schreiben von len Bytes aus buff ab Position pos FileOutputStream void write(int c) void write(char[] void write(char[] int pos, int void write(String Schreiben des Zeichens c Schreiben des Zeichen-Buffers buff Schreiben von len Zeichen aus buff ab Position pos Schreiben des Strings str FileWriter void flush() Herausschreiben aller Schreib-Buffer (Übergabe an das Betriebssystem) FileOutputStream FileWriter int read() Lesen eines Bytes (= Funktionswert) Funktionswert == -1 bei Dateiende Lesen einer Byte-Folge, Ablage im Buffer buff Funktionswert : Anzahl gelesener Bytes bzw –1 bei Dateiende FileInputStream buff) buff, len) str) int read(byte[] buff) int read() int read(char[] buff) long skip(long n) Lesen eines Zeichens (= Funktionswert) FileReader Funktionswert == -1 bei Dateiende Lesen einer Zeichen-Folge, Ablage im Buffer buff Funktionswert : Anzahl gelesener Zeichen bzw –1 bei Dateiende Überlesen der nächsten n Bytes bzw der nächsten n Zeichen FileInputStream FileReader Es existieren noch weitere Methoden, mit denen auch Teile eines Byte- bzw Zeichen-Arrays gelesen bzw Teile eines Strings geschrieben werden können. Alle Methoden für den Dateizugriff werfen eine IOException, wenn ein I/O-Fehler auftritt. alle Methoden sind mit der throws-Klausel throws IOException definiert. FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK BEREICH DATENTECHNIK V – JV – 354 – 03 – TH – 01 ----------------------------------------------------------------------------------- Dateizugriff in Java (4-3) • Demoprogramm zum Dateizugriff (Kopieren einer Datei) // FileCopy.java import java.io.*; public class FileCopy { public static void main(String[] args) { if (args.length <2) System.out.println("Aufruf : \"java FileCopy quelldatei zieldatei\""); else { try { File ifile = new File(args[0]); FileInputStream in = new FileInputStream(ifile); FileOutputStream out = new FileOutputStream(args[1]); long fsize = ifile.length(); System.out.print("Kopiert wird \"" + args[0]+ "\" (Laenge : "); System.out.println(fsize + " Bytes) nach \"" + args[1]+ "\""); byte[] buff = new byte[512]; int len; while ((len=in.read(buff))>=0) { out.write(buff, 0, len); } out.close(); in.close(); System.out.println("Kopieren der Dateien erfolgreich"); } catch(IOException ex) { System.out.println("Exception : " + ex.getMessage()); } } } } Beispiel für Programmaufruf und -ausgabe E:\Java\fhm\ee\vorl\fileacc>java FileCopy ListDir.class ListDir.bin Kopiert wird "ListDir.class" (Laenge : 1100 Bytes) nach "ListDir.bin" Kopieren der Dateien erfolgreich FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 355 – 01 – TH – 02 ----------------------------------------------------------------------------------- Dateizugriff in Java (5-1) • Schreiben und Lesen von Daten in Binärdarstellung ◇ Dies wird durch die beiden Klassen DataOutputStream und DataInputStream ermöglicht ◇ Diese beiden Klassen implementieren jeweils ein Interface zum Schreiben bzw Lesen der internen Binärdarstellung von Werten der einfachen Datentypen in bzw aus Streams und damit auch in bzw aus Dateien. Zusätzlich ermöglichen sie eine effiziente Umcodierung zwischen 16-Bit-Unicode-Zeichen und Bytefolgen für das Schreiben/Lesen von Strings (modifizierte UTF-8-Codierung) ◇ Objekte dieser Klassen wirken als Filter, die einen zugrundeliegenden Byte-Stream in geeigneter Weise umsetzen. Eine Referenz auf das zu filternde Byte-Stream-Objekt ist ihrem Konstruktor als Parameter zu übergeben : ▻ public DataOutputStream(OutputStream out) ▻ public DataInputStream(InputStream in) Das zu filternde Stream-Objekt kann natürlich auch ein Objekt der Klasse FileOutputStream (abgeleitet von OutputStream) bzw FileInputStream (abgeleitet von InputStream) sein. DataInputStream FileInputStream ◇ Wichtigste Methoden der von DataOutputStream bzw DataInputStream implementierten Interfaces : DataOutputStream (Schreiben) void void void void void void void void void void void writeBoolean(boolean b) writeByte(int b) writeChar(int c) writeShort(int s) writeInt(int i) writeLong(long l) writeFloat(float f) writeDouble(double d) writeBytes(String str) writeChars(String str) writeUTF(String str) void write(int b) void write(byte[] ba) void write(byte[] ba, int off, int len) DataInputStream (Lesen) Datentyp boolean readBoolean() byte readByte() char readChar() short readShort() int readInt() long readLong() float readFloat() double readDouble() ----String readUTF() boolean byte char short int long float double String als Byte-Folge String als Char-Folge String (UTF-8-Cod.) int read() int read(byte[] ba) int read(byte[] ba, int off, int len byte byte-Array byte-Array (Länge len ab Offset off) Alle Methoden für den Stream-Zugriff werfen eine IOException, wenn ein I/O-Fehler auftritt. Die meisten Lese-Methoden werfen beim vorzeitigen Erreichen des Stream-Endes eine EOFException alle Methoden sind mit der throws-Klausel throws IOException definiert. ◇ Beide Klassen stellen noch weitere Methoden zum Stream-Zugriff zur Verfügung. ◇ Anmerkung zur modifizierten UTF-8-Codierung : ▻ UTF = Universal Transfer Format : effiziente Codierung von Unicode-Zeichen durch 1, 2 und 3 Bytes ▻ Zeichen zwischen '\u0001' und '\u007F' durch ein Byte : 01 ... 7F Zeichen zwischen '\u0080' und '\u07FF' durch zwei Bytes : C2 80 ... DF BF Zeichen zwischen '\u0800' und '\uFFFF' durch drei Bytes : E0 A0 80 ... EF BF BF der NUL-Character (das Zeichen '\u0000') durch zwei Bytes : C0 80 ▻ writeUTF(str) schreibt vor der eigentlichen den String str codierenden Bytefolge deren Länge als short-Wert (2 Bytes) in den Stream. FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK BEREICH DATENTECHNIK V – JV – 355 – 02 – TH – 02 ----------------------------------------------------------------------------------- Dateizugriff in Java (5-2) • Demoprogramm zum Schreiben von Daten in Binärdarstelung // DataStreamDemo.java import java.io.*; public class DataStreamDemo { public static String byteToHex(byte b) { String str = Integer.toHexString(b & 0x00FF); if (str.length() == 1) str = '0' + str; return str; } public static void main(String[] args) { if (args.length <1) System.out.println("Aufruf : \"java DataStreamDemo dateipfad\""); else { try { File fil = new File(args[0]); FileOutputStream fout = new FileOutputStream(fil); DataOutputStream dout = new DataOutputStream(fout); dout.writeBoolean(true); dout.writeInt(124); dout.writeDouble(3.14); dout.writeUTF("Hallo Java-Freunde"); dout.writeUTF("\u007F\u0080\u07FF\u0800\uFFFF\u0000"); dout.close(); FileInputStream fin = new FileInputStream(fil); System.out.println("Inhalt der Datei \"" + args[0] + "\" :"); int b; int cnt = 0; while((b=fin.read())!=-1) { cnt++; String hex = byteToHex((byte)b); System.out.print(hex + ' '); if (cnt%25 == 0) System.out.println(); } System.out.println(); fin.close(); } catch(IOException ex) { System.out.println("Exception : " + ex.getMessage()); } } } } Programmaufruf und -ausgabe E:\Java\fhm\ee\vorl\fileacc>java DataStreamDemo demo.dat Inhalt der Datei "demo.dat" : 01 00 00 00 7c 40 09 1e b8 51 eb 85 1f 00 12 48 61 6c 6c 6f 20 4a 61 76 61 2d 46 72 65 75 6e 64 65 00 0d 7f c2 80 df bf e0 a0 80 ef bf bf c0 80 FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 356 – 01 – TH – 03 ------------------------------------------------------------------------------------ Dateizugriff in Java (6-1) • Zugriff zu Textdateien ◇ Der Zugriff zu Textdateien erfolgt sinnvollerweise über puffernde Zeichen-Stream-Objekte. Diese werden durch die Klassen BufferedWriter (abgeleitet von Writer) und BufferedReader (abgeleitet von Reader) zur Verfügung gestellt. ◇ Die Objekte beider Klassen kapseln jeweils ein anderes Writer- bzw Reader-Objekt. Eine Referenz auf dieses ist dem jeweiligen Konstruktor als Parameter zu übergeben. ▻ public BufferedWriter(Writer out) ▻ public BufferedReader(Reader in) Durch Verwendung eines FileWriter- (indirekt abgeleitet von Writer) bzw FileReader- (indirekt abgeleitet von Reader) Objekts als Konstruktor-Parameter erhält man pufferende Zeichen-Stream-Objekte für den Dateizugriff. BufferedReader FileReader ◇ Obige Konstruktoren erzeugen Zeichen-Stream-Objekte, deren Puffer eine Standard-Default-Größe besitzen. Diese Grösse ist für die meisten Anwendungsfälle groß genug. Es existieren aber auch Konstruktoren, denen die Puffergröße als zweiter Parameter zu übergeben ist. ◇ Methoden der Klassen BufferedWriter und BufferedReader ▻ Beide Klassen stellen alle Methoden des jeweiligen Stream-Zugriffs-Interfaces der Klassen FileWriter bzw FileReader sowie die Methode close() zur Verfügung ▻ Darüberhinaus besitzen sie aber einige zusätzliche Memberfunktionen : Methode Wirkung existiert für Klasse void newLine() Schreiben eines Zeilenendes BufferedWriter String readLine() Lesen einer Zeile, Rückgabe als String Rückgabe von null, wenn am Dateiende BufferedReader Auch diese Methoden werfen eine IOException, wenn ein I/O-Fehler auftritt. sie sind mit der throws-Klausel throws IOException definiert. ▻ Zusätzlich verfügt die Klasse BufferedReader über Memberfunktionen zum Markieren und späteren Wiedereinnehmen einer bestimmten Position im Stream. • Weitere Stream-Filter-Klassen ◇ Im Package java.io sowie in einigen anderen Packages (z.B. java.util.zip) sind noch weitere StreamKlassen enthalten, die als Filter von anderen Stream-Objekten und damit auch von File-Stream-Objekten eingesetzt werden können. Dadurch lassen sich File-Stream-Objekte mit weiteren speziellen Eigenschaften versehen. ◇ Beispiele : FilterReader LineNumberReader PrintWriter PrintStream PushbackInputStream CheckedOutputStream abstrakte Basisklasse für – eigene – Reader-Filter-Klassen Klasse zum zeilenorientierten Lesen aus Zeichen-Streams Klasse zur Ausgabe der externen Darstellung von Datenwerten in Zeichen-Streams Klasse zur Ausgabe der externen Darstellung von Datenwerten in Byte-Streams Klasse, die die Rückgabe gelesener Bytes in einen Eingabe-Byte-Stream ermöglicht Klasse, die an einen Ausgabe-Stream eine Prüfsumme anhängt. FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK BEREICH DATENTECHNIK V – JV – 356 – 02 – TH – 01 ----------------------------------------------------------------------------------- Dateizugriff in Java (6-2) • Demoprogramm zum Zugriff zu Textdateien : Ausgabe einer Textdatei am Bildschirm // TextFileList.java import java.io.*; public class TextFileList { public static void main(String[] args) { if (args.length <1) System.out.println("Aufruf : \"java TextFileList dateipfad\""); else { try { File fil = new File(args[0]); if (!fil.exists()) System.out.println("Datei \"" + args[0] + "\" existiert nicht"); else { BufferedReader tf = new BufferedReader(new FileReader(args[0])); String line; while ((line=tf.readLine()) != null) System.out.println(line); tf.close(); } } catch(IOException ex) { System.out.println("Exception : " + ex.getMessage()); } } } } FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 356 – 03 – TH – 02 ------------------------------------------------------------------------------------ Dateizugriff in Java (6-3) • Formatiertes Schreiben in Textdateien (ab dem JDK 5.0) ◇ Mittels eines Objekts der Klasse Formatter ▻ Die Klasse Formatter (Package java.util) dient zum Erzeugen formatierter Textdarstellungen. Formatter-Objekte können auch an Dateien gebunden werden. Damit lassen sie sich zur formatierten Ausgabe in Textdateien einsetzen. ▻ Die jeweilige Datei ist durch Übergabe eines die Datei referierenden Objekts an den Konstruktor festzulegen. Ein derartiges Objekt kann u.a. sein : ▹ Objekt der Klasse FileOutputStream (z.B. Konstruktor Formatter(OutputStream os)) ▸ Objekt der Klasse FileWriter (z.B. Konstruktor Formatter(Appendable a)) ▸ Objekt der Klasse File (z.B. Konstruktor Formatter(File file)) Formatter FileOutputStream Formatter FileWriter Formatter File ▻ Mit der Formatter-Methode Formatter format(String format, Object... args) kann formatierter Text in die Datei geschrieben werden. Die Parameter entsprechen den Parametern der PrintStream-(und PrintWriter-) Methode printf() : - format ist der anzuwendende Format-String Syntax und Semantik des Format-Strings ist die gleiche wie beim Format-String der Methode printf() - args sind die zu schreibenden (und in Textdarstellung umzuwandelnden) Werte Rückgabewert : aktuelles Formatter-Objekt ▻ Beispiel : public void formOutDouble1(String dpfad, int anz) throws IOException { File datei = new File(dpfad); //Formatter form = new Formatter(datei); //Formatter form = new Formatter(new FileOutputStream(datei)); Formatter form = new Formatter(new FileWriter(datei)); Random rand = new Random(); for (int j=1; j<=anz; ++j) { form.format("%.5f ", rand.nextDouble()); if (j%8==0) form.format("%n"); } form.close(); } FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 356 – 04 – TH – 01 ----------------------------------------------------------------------------------- Dateizugriff in Java (6-4) • Formatiertes Schreiben in Textdateien, Forts. (ab dem JDK 5.0) ◇ Mittels der PrintStream- (und PrintWriter-) Methode printf() ▻ Die – u.a. für die Standardausgabe eingesetzte –Klasse PrintStream ermöglicht die Ausgabe von Strings und der externen Textdarstellung von Datenwerten in beliebige Byte-Streams, somit auch in Dateien. ▻ Analog dient die Klasse PrintWriter zur Ausgabe derartiger Informationen in Zeichen-Streams und damit ebenfalls in entsprechende Dateien. ▻ Für beide Klassen ist die Datei bei der Objekt-Erzeugung durch Übergabe eines sie referierenden Objekts an den jeweiligen Konstruktor festzulegen. U.a. existieren die folgenden Konstruktoren : ▹ PrintStream(OutputStream os) (OutputStream ist u.a. Basisklasse von FileOutputStream) ▹ PrintStream(File file) ▹ PrintWriter(Writer out) (Writer ist u.a. Basisklasse von FileWriter) ▹ PrintWriter(File file) PrintStream FileOutputStream PrintStream File PrintWriter FileWriter PrintWriter File ▻ Beide Klassen stellen ab dem JDK 5.0 zur formatierten Ausgabe die Memberfunktion printf() zur Verfügung ▹ Klasse PrintStream : PrintStream printf(String format, Object... args) ▹ Klasse PrintWriter : PrintWriter printf(String format, Object... args) Beschreibung der Parameter sowie der Wirkungsweise der Funktion siehe "Standardausgabe - Formatierte Ausgabe" ▻ Beispiel : public void formOutDouble2(String dpfad, int anz) throws IOException { File datei = new File(dpfad); PrintStream prnt = new PrintStream(datei); //PrintStream prnt = new PrintStream(new FileOutputStream(datei)); //PrintWriter prnt = new PrintWriter(datei); //PrintWriter prnt = new PrintWriter(new FileWriter(datei)); Random rand = new Random(); for (int j=1; j<=anz; ++j) { prnt.printf("%.5f ", rand.nextDouble()); if (j%8==0) prnt.printf("%n"); } prnt.close(); } FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK FG TECHNISCHE INFORMATIK V – JV – 356 – 05 – TH – 02 ----------------------------------------------------------------------------------- Dateizugriff in Java (6-5) • Formatiertes Lesen aus Textdateien (ab dem JDK 5.0) ◇ Hierfür lässt sich die Klasse Scanner einsetzen ◇ Scanner-Objekte dienen zum Zergliedern und Interpretieren von Zeichenfolgen. Diese Zeichenfolgen können auch von Zeichen- und Byte-Streams und damit auch von Dateien geliefert werden. ◇ Die jeweilige Zeichenquelle ist einem Scanner-Objekt im Konstruktor zu übergeben, u.a. als Objekt der ▻ Klasse FileInputStream (Konstruktor Scanner(InputStream source)) ▻ Klasse FileReader (Konstruktor Scanner(Readable source)) ▻ Klasse File (Konstruktor Scanner(File source)) Scanner File *) *) bzw FileInputStream oder FileReader ◇ Beschreibung der Funktionalität der Klasse Scanner siehe "Standard- Ein- und Ausgabe in Java". ◇ Beispiel : Funktion zum Lesen aus Textdateien, deren Inhalt prinzipiell wie folgt aufgebaut ist. Die gelesenen Werte werden im gleichen Format in die Standard-Ausgabe ausgegeben (Memberfunktion der Klasse FormTextFileDemo) 2 3 1 6 3 : : : : : 0,44507 0,25472 0,96712 0,78277 0,54464 0,06490 0,13943 0,40664 0,24195 0,03770 0,54913 0,15014 0,99872 0,71365 0,14333 public void formInput() throws IOException { // String dpfad ist Datenkomponente der Klasse FormTextFileDemo File datei = new File(dpfad); Scanner scan = new Scanner(datei); //Scanner scan = new Scanner(new FileInputStream(datei)); //Scanner scan = new Scanner(new FileReader(datei)); try { while (scan.hasNext()) { int anz = scan.nextInt(); System.out.printf("%d : ", anz); scan.next(); // Ueberlesen des ':' double d; for (int i = 1; i <= anz; ++i) { d = scan.nextDouble(); System.out.printf("%.5f ", d); } System.out.printf("%n"); } } catch (InputMismatchException ex) { System.err.println("Type Mismatch beim Lesen."); } scan.close(); } FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK BEREICH DATENTECHNIK V – JV – 357 – 01 – TH – 03 ----------------------------------------------------------------------------------- Dateizugriff in Java (7-1) • Wahlfreier Zugriff zu Dateien ◇ Für den wahlfreien Zugriff zu Dateien steht die Klasse RandomAccessFile zur Verfügung. Diese Klasse ist von keiner der File-Stream-Klassen sondern direkt von Object abgeleitet. ◇ Durch Objekte dieser Klasse können Dateien für einen wahlfreien Zugriff nur zum Lesen oder zum Lesen und Schreiben geöffnet werden. Der wahlfreie Zugriff wird durch die Möglichkeit zur expliziten Veränderung der aktuellen Bearbeitungsposition (File-Pointer) realisiert. ◇ Konstruktoren der Klasse RandomAccessFile ▻ public RandomAccessFile(String path, String mode) throws FileNotFoundException ▻ public RandomAccessFile(File fil, String mode) throws FileNotFoundException Der erste Parameter referiert die zu bearbeitende Datei (über den Zugriffspfad bzw ein File-Objekt, das diesen repräsentiert) Der zweite Parameter legt die Zugriffsart fest : ▻ "r" nur Lesen, ▻ "rw" Lesen und Schreiben. ("rws" und "rwd" sind auch zulässig) Die Konstruktoren versuchen die referierte Datei für die angegebene Zugriffsart zu öffnen. Falls die referierte Datei nicht existiert wird bei der Zugriffsart "rw" versucht, sie zu erzeugen. Die Konstruktoren können die folgenden Exceptions werfen : ▻ FileNotFoundException, falls die referierte Datei nicht existiert (Zugriffsart "r") oder ein Directory ist oder nicht erzeugt werden kann oder aus einem anderen Grund nicht geöffnet werden kann. ▻ SecurityException, falls für die vorgesehene Zugriffsart keine Berechtigung besteht ▻ IllegalArgumentException, falls ein nicht zulässiger String für die Zugriffsart angegeben wird. ◇ Methoden der Klasse RandomAccessFile zum Dateizugriff : Die Klasse stellt für den Dateizugriff die gleichnamigen Methoden mit gleicher Signatur wie die Klassen DataInputStream und DataOutputStream zur Verfügung. Wie bei diesen Klassen werfen die Zugriffsmethoden eine IOException beim Auftritt eines I/O-Fehlers. Die meisten Lesemethoden werfen darüber hinaus eine EOFException beim vorzeitigen Erreichen des Dateiendes ◇ Weitere Methoden der Klasse RandomAccessFile (Auswahl) Methode Wirkung Setzen der Bearbeitungsposition auf pos Bytes nach dem Dateianfang Rückgabe der aktuellen Bearbeitungsposition (in Bytes bezogen auf den Dateianfang) int skipBytes(int cnt) Versuch, die Bearbeitungsposition um cnt Bytes weiterzusetzen Rückgabe der Anzahl Bytes, um die tatsächlich weitergesetzt wurde void seek(long pos) long getFilePointer() String readLine() Lesen der nächsten Zeile (=Rückgabewert), Bytes werden zu Zeichen ergänzt (höherwertiges Byte == NUL-Byte) long length() Rückgabe der Dateilänge FileDescriptor getFD() Rückgabe des assoziierten FileDescriptor-Objekts void close() Schliessen der Datei und Freigabe aller belegten Resourcen Alle o.a. Methoden werfen eine IOException wenn ein I/O-Fehler auftritt. sie sind mit der throws-Klausel throws IOException definiert. FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK BEREICH DATENTECHNIK V – JV – 357 – 02 – TH – 02 ----------------------------------------------------------------------------------- Dateizugriff in Java (7-2) • Demoprogramm zum wahlfreien Dateizugriff // RandAccDemo.java // Zufallsgesteuerte Auswahl eines Spruches aus einer Textdatei mit Spruechen. // Die einzelnen Sprueche sind jeweils durch eine Zeile, // die nur das Zeichen '*' enthaelt, getrennt. import java.io.*; public class RandAccDemo { public static void main(String[] args) { try { RandomAccessFile raf = new RandomAccessFile("sprueche.txt", "r"); long pos = (long)(raf.length()*Math.random()); raf.seek(pos); while((pos!=0) && ((char)raf.read()!='*')) raf.seek(--pos); int ch; if (pos==0) System.out.println(); while (((ch=raf.read())!=-1) && ((char)ch!='*')) { System.out.print((char)ch); } System.out.println(); raf.close(); } catch (IOException ex) { System.out.println(ex); } } } Beispiele für Programmaufruf und -ausgabe E:\Java\fhm\ee\vorl\fileacc>java RandAccDemo Gut gehaengt ist besser als schlecht verheiratet. E:\Java\fhm\ee\vorl\fileacc>java RandAccDemo Es ist nicht genug, dass man redet, man muss auch richtig reden. E:\Java\fhm\ee\vorl\fileacc>java RandAccDemo Ein Tor nur schliesst aus aeusserem Gehaben getrost auf eines Menschen innere Gaben. FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK BEREICH DATENTECHNIK V – JV – 358 – 00 – TH – 01 ------------------------------------------------------------------------------------ Dateizugriff in Java – Zusammenfassender Überblick Datei- bzw Verwendungsart Klasse Konstruktorparameter (Auswahl) wichtige Zugriffsmethoden sequentieller byteweiser Zugriff FileInputStream FileOutputStream File-Objekt oder Dateizugriffspfad read() write() sequentieller zeichenweiser Zugriff FileReader FileWriter File-Objekt oder Dateizugriffspfad read() write() Lesen/Schreiben von Daten in Binärdarstellung DataInputStream DataOutputStream FileInputStream-Obj. FileOutputStream-Obj. readInt() usw writeInt() usw Lesen/Schreiben von Textdateien BufferedReader FileReader-Objekt read() readLine() BufferedWriter FileWriter-Objekt write() newLine() Formatter File-Objekt oder FileWriter-Objekt oder FileOutputStream-Obj format() PrintStream File-Objekt oder FileOutputStream-Obj printf() PrintWriter File-Objekt oder FileWriter-Objekt printf() Formatiertes Lesen aus Textdateien Scanner File-Objekt oder FileReader-Objekt oder FileInputStream-Obj. nextLine() hasNextLine() next() hasNext() nextInt() usw wahlfreier Zugriff RandomAccessFile File-Objekt oder Dateizugriffspfad + Zugriffsmodus (String) seek() getFilePointer() skipBytes() read() readLine() readInt() usw write() writeInt() usw length() Formatiertes Schreiben in Textdateien