270 likes | 359 Views
Programmierpraktikum Java SS 2005. Mag.Thomas Hilpold Institut für Wirtschaftsinformatik Software Engineering JKU Linz. Wiederholung (1). InputStreams und OutputStreams. InputStreams und OutputStreams sind zur Ein/Ausgabe von bytes geeignet
E N D
Programmierpraktikum JavaSS 2005 Mag.Thomas Hilpold Institut für Wirtschaftsinformatik Software Engineering JKU Linz
Wiederholung (1) InputStreams und OutputStreams • InputStreams und OutputStreams sind zur Ein/Ausgabe von bytes geeignet • Sie eignen sich schlecht zum Lesen und Schreiben von Text, da in Java Unicode verwendet wird (2 Bytes) • Man kann Daten, wie ints, Doubles, et.c. zwar mit Streams schreiben; allerdings sind die erstellten Dateien nicht von Menschen lesbar
Wiederholung (2) Readers and Writers • Plattform: • 1 Zeichen = 1 Byte • Java verwendet Unicode: • 1 Zeichen = 2 Bytes, weltweiter Standard • Readers und Writers sind in der Anwendung sehr änhlich zu Input/OutputStreams • Der Datentyp ist dabei Character (Unicode), nicht Byte.
Reader Einleitung • Wie kann man vom Menschen lesbare Dateien mit Java-Technologie einlesen und verarbeiten? • Speichern und Laden von einfachen Werten (zB. int) • Einstellungen für Programme (zB. space.ini) • exportieren/importieren von Tabellen • einfache Persistenz für Objekte • u.s.w.
Reader Die abstrakte Klasse Reader int read() int read(char[] cbuf) //nr or –1 int read(char[] cbuf, int off, int len) abstract void close() abstract void flush() ... • Erst Unterklassen ermöglichen tatsächliche Anwendung • int bei read() zur Vereinfachung der Anwendung, eigentlich Character (2 relevante bytes, Unicode) • Mit Readers liest man immer Characters, niemals Bytes • Einem Reader liegt häufig ein Stream zugrunde. Der Reader führt die Konvertierung der bytes zu characters unter Berücksichtigung des Encoding durch.
Reader Relevante Klassen Reader BufferedReader InputStreamReader PrintReader???? effizient readLine() – Methode (Erkennt Ende durch \r, \n oder \r\n) minimal, kann von Inputstream lesen Konvertiert bytes ->chars(Encoding) gibt es nicht readInt() readDouble()
InputStreamReader Methoden und Funktionalität InputStreamReader(InputStream in) InputStreamReader(InputStream in, String enc) int read() String getEncoding() ... • Konstruktor ohne enc verwendet Encoding der Plattform • enc: Cp850 (Dos, Deutschland, Ö), Cp1252 (Windows, De, Ö) • bytes des Streams werden zu chars konvertiert
BufferedReader Methoden und Funktionalität BufferedReader(Reader in) BufferedReader(Reader in, int sz) String readLine() // string or null (end reached) ... • Erwartet einen Reader im Konstruktor • keine Konvertierung • kann ganze Zeilen lesen • Erkennt Terminierung einer Zeile durch \r, \n oder \r\n (unix, mac, windows, dos)
PrintReader ??? Problem file: persons.txt Franz;Öllinger;Hagenberg 1;5020 Salzburg;38783 Eva;Huber;Neustr. 34;1040 Wien;73821 • ZB.: sollen Objekte einer fiktiven Klasse Person erzeugt werden, die mit den Daten aus dem File initialisiert werden • Jede Zeile enthält eine Person • ; oder | oder :, ... (Delimiter, Begrenzer) • ; Darf nicht in Daten vorkommen • Verschiedene Typen: String, int, ev. double, ...
PrintReader ??? Lösungsidee • Zeile für Zeile einlesen (dabei soll konvertiert werden, z.B. Dos) • Zeile zerlegen, sodaß ein String für jedes Datenfeld entsteht"Franz", "Öllinger", "Hagenberg 1", "5020 Salzburg", "38738" • Strings in entsprechenden Datentyp konvertieren zB. "1234" -> int 1234
PrintReader ??? Lösungsidee 2 • Zeile für Zeile einlesen -> BufferedReader • String für jedes Datenfeld -> StringTokenizer • Strings in entsprechenden Datentyp konvertieren -> WrapperKlassenzB.: int i = Integer.parseInt("12342");
BufferedReader Anwendung im Problemfall InputStreamReader inr = new InputStreamReader(new FileInputStream("D:\\persons.txt")); //plattform BufferedReader br = new BufferedReader(inr, 1000);String curline;do { curLine = br.readLine(); if (curLine!=null) { .... }} while (curLine!= null); natürlich try/catch nötig
StringTokenizer Zerlegung der Lines "Franz,"Öllinger","Hagenberg 1","5020 Salzburg","38783" Die Klasse StringTokenizer ermöglicht dies sehr elegant Sie befindet sich im package java.util Alternative: Klasse String Methoden indexOf, subString, .... wesentlich komplizierter Man kann Zeichen angeben, die als Delimiters (Begrenzer) gelten und die sog. Tokens direkt auslesen
StringTokenizer Methoden StringTokenizer(String str) //" \t\n\r\f" StringTokenizer(String str, String delim) //e.g. ";"StringTokenizer(String str, String delim, boolean returnDelims)int countTokens()boolean hasMoreTokens()String nextToken()String nextToken(String delim) Man kann Zeichen angeben, die als Delimiters (Begrenzer) gelten und die sog. Tokens direkt auslesen
StringTokenizer Anwendung im Beispiel String example = " Franz;Öllinger;Hagenberg 1;5020 Salzburg;38783"; StringTokenizer tok = new StringTokenizer(example, ";"); while (tok.hasMoreTokens()) { String curToken = tok.nextToken(); } //curToken = "Franz"; //curToken = "Öllinger"; //... = "38783" -> String, Ziel: int
Wrapper Klassen Primitive Typen und ihre Wrapper-Klassen PrimitiveType NumericType boolean IntegralType FloatingpointType byte short int long char8 – 16 – 32 – 64 - 16 float double32 - 64 • Für jeden PrimitiveType gibt es eine Wrapperklasse, deren Objekte jeweils genau einen solchen Wert kapseln
Wrapper Klassen primitive Types und ihre Wrapper 2 Boolean Character Number Byte Short Integer Long Float Double • Alle Klassen sind im package java.lang untergebracht
Wrapper Klassen Ziel und Zweck • Sind Objects, Polymorphismus kann ausgenutzt werden (zB. Hinzufügen zu einer Liste, die Objects enthalten kann ist mit primitiveTypes nicht möglich) • Stellen einen sinnvollen Platz für häufig benötigte Hilfsoperationen dar (zB. parsen, verschiedene Radixes, Konvertierung) Beispiele Klasse:List Methode: add(Object o);add(12); // nicht möglichadd(new Integer(12)) //ok int i = Integer.parseInt("12342");
Integer Methoden static String toBinaryString(int i) static String toHexString(int i) static String toOctalString(int i) static int parseInt(String s, int radix) static int MIN_VALUE static int MAX_VALUE double doubleValue() ... • Für unser Problem wichtig : int i = Integer.parseInt("1234");
Double Methoden static double parseDouble(String s) static Double valueOf(String s) static double MIN_VALUE static double MAX_VALUE double doubleValue() boolean isInfinite() boolean isNaN() ... • Für unser Problem wichtig : double j = Double.parseDouble("1234.232e8");
Wrapper Klassen Zusammenfassung • Objekte von Wrapper klassen kapseln jeweils einen Wert eines primitiven Typs • Sie stellen nützliche Methoden zur Verfügung • Objekte der Wrapper-Klassen sind Objects und können unter Ausnutzung des Polymorphismus verwendet werden (zB in Collections)
PrintReader ??? Lösung • Zeile für Zeile einlesen -> BufferedReader • String für jedes Datenfeld -> StringTokenizer • Strings in entsprechenden Datentyp konvertieren -> WrapperKlassenzB.: int i = Integer.parseInt("12342");
Streams und die Konsole Bisher • Verwendung der Klasse TextIO zur • Eingabe und Ausgabe auf die Konsole • TextIO ist nicht Teil der Java Klassenbibliothek Jetzt • System.out -> PrintStream (Ausgabe) • System.err -> PrintStream (Ausgabe von Fehlermeldungen) • System.in -> InputStream (Eingabe) Genau diese drei Streams dienen zur Interaktion mit dem Benutzer über die Konsole. Auch die Klasse TextIO hat sich dieser drei Streams bedient.
Ausgabe auf die Konsole System.out und System.err • Der tatsächliche Ort der Ausgabe kann variiren.zB. Dos-Box, Jbuilder-Konsole Fenster, Umleitung in eine Datei, ... • Beiden Klassenvariable sind vom Typ java.io.PrintStream • Es werden keine IO-Exceptions ausgelöst • Auf System.err sollten Fehlermeldungen ausgegeben werden. • Die Trennung der Ausgabe in System.err und System.out ermöglicht z.B. bei Umleitung der Ausgabe in eine Datei, daß dennoch Fehlermeldungen dem Benutzer angezeigt werden können.
Ausgabe auf die Konsole Die Klasse PrintStream • Hat Methoden zur Ausgabe von verschiedenen TypenzB. print(String), print (int), print(char) • Sonderfall !!! Characters werden in plattformspezifische Bytes konvertiert (Default encoding) • Es werden keine Exceptions ausgelöst Methoden void flush() void print(XXXX) void println(XXXX) // inkl newline void println() // only newline void write(int i) // not encoded !! ...
Eingabe von der Konsole System.in (Typ InputStream) • Primitiver InputStream • Keine Berücksichtigung der Codierung • Exceptions können auftreten • Einlesen von ints, doubles, et.c. rel. kompliziert • Die Klasse BufferedReader ist meist am besten geeignet Beispiel (Lese ein int von der Konsole) BufferedReader in = new BufferedReader(new InputStreamReader(System.in); String s = in.readLine(); // blocks until CR int i; if (s != null) { i = Integer.parseInt(s); }
Verkettung von Streams Beispiel BufferedReader in = new BufferedReader(new InputStreamReader(System.in); readLine() read() read() BufferedReader InputStreamReader System.in uses buffer, determines lines encoding into chars ...bytes...