29.03.2004 Wiederholung: Interfaces in Java Wdh.: Modellierung des Dateisystems public interface Verlaengerbar { ... int VERLAENGERUNGSFRIST = 14; int verlaengern (...); ... } verlängerbar {Interface} Verlängerungsfrist Buch public class Buch extends Medium implements Verlaengerbar, Vormerkbar { ... public int verlaengern (...) {...} public int vormerken (...) {...} ... } Autoren Titel Verlag Jahr Anlegen, Öffnen, Schließen und Löschen von Dateien Anlegen und Löschen von Verzeichnissen Abfragen/Setzen von Informationen über Dateien und Verzeichnisse Blättern in der Verzeichnishierarchie • nicht zum Lesen und Schreiben in Dateien! • wird mit Streams realisiert ausleihen verlängern vormerken vormerkbar {Interface} • Beispiel: Länge ausgeben, wenn "java" existiert und eine Datei (kein Verzeichnis) ist File datei = new File("java"); if (datei.exists() && datei.isFile()) { System.out.println(datei.length() + " Bytes"); } • Klassen können nur eine Oberklasse beerben, vormerken aber mehrere Interfaces implementieren, deren Methoden sie alle überschreiben müssen Java-Einführungskurs • mit Objekten der Klasse java.io.File zum • • • • verlängern 1 Java-Einführungskurs 2 Wiederholung: Streams Wdh.: Verwendung von Medienstreams • Unterklassen der abstrakten Klassen • Beispiel: FileOutputStream • InputStream, OutputStream (für Byte-Streams) • Reader, Writer (für Unicode-Zeichenstreams) • Konstruktor öffnet die Datei und • überschreibt ggf. zuvor bestehende Datei • FileOutputStream(File file) • FileOutputStream(String name) • hängt bei append==true an Datei an, überschreibt sonst ggf. • FileOutputStream(File file, boolean append) • FileOutputStream(String name, boolean append) • (alle können FileNotFoundException werfen) • zur Erfüllung bestimmter Aufgaben • • • • Lesen/Schreiben aus/in Datenquellen/-senken Verwendung anderer Streams als Datenquellen/-senken Vor/-Nachverarbeitung der Daten im Stream Ein/-Ausgabe verschiedener Datentypen • i.d.R. müssen mehrere (aber nicht unbedingt alle) dieser Aufgaben gelöst werden ¾ Verkettung von Streams für verschiedene Funktionen • Methoden i.W. wie abstrakter OutputStream • write (Byte oder Byte-Array schreiben), flush (Puffer leeren), etc. • arbeiten auf der vom Stream gekapselten Datei Quelle Medium Senke Medium Verknüpfung Filterung Datentypen Filterung Datentypen Quelle Programm Verknüpfung Senke Java-Einführungskurs 3 Medium Verknüpfung File OutputStream Verknüpfung Filterung Datentypen Filterung Datentypen Programm Java-Einführungskurs 4 Wdh.: Verwendung von Datenstreams Wdh.: Schreiben in eine Textdatei • Beispiel: DataOutputStream • FileWriter kann Zeichen in eine Datei schreiben • PrintWriter kann Daten als Strings in Stream schreiben • Konstruktor nimmt zugrunde liegenden Stream entgegen • über mit div. Datentypen überladene print/println-Methoden • Umwandlung von Referenzdatentypen in Strings mit toString() • DataOutputStream(OutputStream out) • Methoden wie abstrakter OutputStream, zusätzlich auch: • • • • • • void void void void void void writeBoolean(boolean v) writeShort(int v), void writeByte(int v) writeInt(int v), void writeLong(long v) writeFloat(float v), void writeDouble(double v) writeChar(int v), void writeUTF(String str) writeBytes(String s), void writeChars(String s) • schreiben primitive Typen in passender Byte-Darstellung in Stream Quelle Medium Senke Medium Java-Einführungskurs Verknüpfung Verknüpfung Filterung Datentypen Filterung Data OutputStream Programm Buch javaBuch = new Buch(...); float preis = 41.99; try { FileWriter fw = new FileWriter("ausgabe.txt"); PrintWriter pw = new PrintWriter(fw); pw.println(javaBuch); pw.println(preis); } catch (IOException e) {...} ausgabe .txt 5 Lehrstuhl für Angewandte Telematik/e-Business Java-Einführungskurs FileWriter PrintWriter Programm 6 1 29.03.2004 Wdh.: Serialisierung von Objekten Ü5.1 Aufteilen von Dateien • FileOutputStream kann Bytes in eine Datei schreiben • ObjectOutputStream kann Objekte in Bytes wandeln • 1. Schreiben Sie sich eine Textdatei, in die Sie positive und negative ganze Zahlen eingeben. Dazu eignet sich jeder Texteditor. • über write-Methoden für diverse primitive und Referenzdatentypen • Umwandlung von Referenzdatentypen in Bytes passiert automatisch 12 13 -12 -14 Buch javaBuch = new Buch(...); float preis = 41.99; try { FileOutputStream fos = new FileOutputStream("ausgabe.ser"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(javaBuch); oos.writeFloat(preis); } catch (IOException e) {...} ausgabe .ser File Object OutputStream OutputStream 14 17 2. Schreiben Sie dann ein Java-Programm, das diese Textdatei einliest und alle positiven Zahlen in einer Textdatei positiv.txt und alle negativen Zahlen in einer Datei negativ.txt speichert. Programm Java-Einführungskurs 7 Java-Einführungskurs Ü5.1.2 Aufteilen von Dateien Ü5.1.2 Aufteilen von Dateien import java.io.*; public void arbeite() throws FileNotFoundException, IOException { positiv = new PrintWriter(new FileWriter("positiv.txt")); negativ = new PrintWriter(new FileWriter("negativ.txt")); public class Aufteilen { 8 FileReader fr = new FileReader("eingabe.txt"); private PrintWriter positiv; private PrintWriter negativ; int c; StringBuffer buf = new StringBuffer(); // Zeichen einlesen while ((c = fr.read()) != -1) { // Wenn Leer- oder Trennzeichen: verarbeiten! if ((c == '\n') || (c == '\t') || (c == ' ') || (c == '\r')) { verarbeite(buf.toString()); buf = new StringBuffer(); } else buf.append((char) c); // ansonsten Zeichen sammeln } private void verarbeite(String inhalt) { ... } public void arbeite() throws FileNotFoundException, IOException { ... } public static void main(String[] args) throws FileNotFoundException, IOException { Aufteilen aufteilen = new Aufteilen(); aufteilen.arbeite(); } verarbeite(buf.toString()); // ggf. restliche Zeichen verarbeiten fr.close(); positiv.close(); negativ.close(); } } Java-Einführungskurs 9 Java-Einführungskurs 10 Ü5.1.2 Aufteilen von Dateien Ü5.1.3 Aufteilen von Dateien private void verarbeite(String inhalt) { inhalt = inhalt.trim(); // Leerzeichen von String entfernen 3. Erweitern Sie Ihr Programm so, dass nach dem Aufteilen der Daten die Dateien positiv.txt und negativ.txt an der Konsole ausgegeben werden. if (inhalt.length() != 0) { // wenn String != Leerstring try { // String in int umwandeln int i = Integer.parseInt(inhalt); // je nach Vorzeichen in entsprechende Datei schreiben if (i < 0) negativ.println(i); else positiv.println(i); } catch (NumberFormatException nfe) { // bei Umwandlungsfehler Meldung ausgeben nfe.printStackTrace(); } } public static void main(String[] args) throws FileNotFoundException, IOException { Aufteilen aufteilen = new Aufteilen(); aufteilen.arbeite(); // ab hier beginnt die Ausgabe aufteilen.ausgabe("positiv.txt"); aufteilen.ausgabe("negativ.txt"); } Java-Einführungskurs } 11 Lehrstuhl für Angewandte Telematik/e-Business Java-Einführungskurs 12 2 29.03.2004 Ü5.1.3 Aufteilen von Dateien Ü5.2.1 DirectoryDirectory-Lister 1. Schreiben Sie eine Klasse DirectoryLister, die eine Methode enthält, die alle Dateinamen aus einem Verzeichnis auf der Konsole auflistet. private void ausgabe(String filename) throws IOException, FileNotFoundException { import java.io.*; BufferedReader br = new BufferedReader( new FileReader(filename)); public class DirectoryLister { public void doList(String directory) { File dir = new File(directory); String list[] = dir.list(); String line; System.out.println("Ausgabe von " + filename); for (int i = 0; i < list.length; i++) System.out.println(list[i]); } while ((line = br.readLine()) != null) System.out.println(line); public static void main(String args[]) { DirectoryLister dl = new DirectoryLister(); dl.doList("."); } br.close(); } } Java-Einführungskurs 13 Java-Einführungskurs 14 Ü5.2.2 DirectoryDirectory-Lister Ü5.2.3 DirectoryDirectory-Lister 2. Geben Sie das Interface ListerCallback ein und speichern Sie es ab, so dass Sie es in Ihrem Programm verwenden können. 3. Modifizieren Sie die Klasse DirectoryLister so, dass bei ihrem Konstruktor eine Referenz auf ein Objekt, das ListerCallback implementiert, übergeben werden kann (...) import java.io.*; import java.io.*; public class DirectoryLister { interface ListerCallback { public void perform(File theFile); } private ListerCallback lcb; public DirectoryLister(ListerCallback lcb) { this.lcb = lcb; } ... } Java-Einführungskurs 15 Java-Einführungskurs 16 Ü5.2.3 DirectoryDirectory-Lister Ü5.2.4 DirectoryDirectory-Lister 3. (...) Ändern Sie den Rest der Klasse so, dass zum Ausgeben der Dateien die perform()-Methode von ListerCallback verwendet wird. Also sollte irgendwo in Ihrem Programm für jede Datei, die Sie ausgeben wollen, einmal ListerCallback.perform(...) aufgerufen werden. 4. Wenn Sie Ihr Programm nun ausführen wollen, brauchen Sie ja ein Objekt, das ListerCallback implementiert. Nehmen Sie dazu die folgende Klasse: (...) import java.io.*; public class CallbackTest implements ListerCallback { public void perform(File theFile) { System.out.println(theFile.getName()); } } public void doList(String directory) { File dir = new File(directory); String list[] = dir.list(); for (int i = 0; i < list.length; i++) { File f = new File(list[i]); lcb.perform(f); } } Java-Einführungskurs 17 Lehrstuhl für Angewandte Telematik/e-Business Java-Einführungskurs 18 3 29.03.2004 Ü5.2.4 DirectoryDirectory-Lister Ü5.3.1 Lines of Code 4. (...) Ändern Sie Ihr Programm so, dass beim Erzeugen der Instanz von DirectoryLister eine Referenz auf ein Objekt vom Typ CallbackTest übergeben wird. 1. Schreiben Sie eine Klasse InspectCode, die das Interface ListerCallback aus der zweiten Aufgabe implementiert. Als Ergebnis soll die InspectCode.perform()-Methode die Anzahl der Zeilen in dieser Datei ausgeben. (...) import java.io.*; public static void main(String args[]) { DirectoryLister dl = new DirectoryLister(new CallbackTest()); dl.doList("."); } public class InspectCode implements ListerCallback { public void perform(File theFile) { int lines = 0; String line; try {...} catch (IOException ioe) {...} } } Java-Einführungskurs 19 Ü5.3.1 Lines of Code Java-Einführungskurs Ü5.3.1 Lines of Code 1. (...) Der perform()-Methode sollen aber nun nur Textdateien vom Typ „.java“ übergeben werden. Nehmen Sie die dazu nötigen Änderungen in der Klasse DirectoryLister aus der zweiten Aufgabe vor. try { BufferedReader bfr = new BufferedReader( new FileReader(theFile)); while ((line = bfr.readLine()) != null) { lines++; } public int doList(String directory) { File dir = new File(directory); String list[] = dir.list(); System.out.println("File " + theFile.getName() + " has " + lines + " Lines."); bfr.close(); for (int i = 0; i < list.length; i++) { File f = new File(list[i]); if (list[i].endsWith(".java")) lcb.perform(f); } catch (IOException ioe) { ioe.printStackTrace(); } Java-Einführungskurs 20 } } 21 Java-Einführungskurs Ü5.3.1 Lines of Code Ü5.3.2 Lines of Code • Statt des CallbackTest-Objekts aus Ü5.2.4 übergeben wir dem Konstruktor von DirectoryLister nun ein Objekt unserer neuen InspectCode-Klasse: 2. Modifizieren Sie die Klasse InspectCode, so dass bei der Zählung der Zeilen Kommentare in Java-Programmen nicht berücksichtigt werden. 22 import java.io.*; public static void main(String args[]) { DirectoryLister dl = new DirectoryLister(new InspectCode()); public class InspectCode implements ListerCallback { public void perform(File theFile) { int lines = 0; String line; boolean comment = false; dl.doList("."); } try { BufferedReader bfr = new BufferedReader( new FileReader(theFile)); Java-Einführungskurs 23 Lehrstuhl für Angewandte Telematik/e-Business Java-Einführungskurs 24 4 29.03.2004 Ü5.3.2 Lines of Code Ü5.3.2 Lines of Code while ((line = bfr.readLine()) != null) { ... line = line.trim(); if (comment) { // wir lesen gerade einen Kommentarabschnitt int i = line.indexOf("*/"); if (i != -1) { comment = false; line = line.substring(i + 2); } else line = ""; } else { // wir lesen gerade einen Quelltextabschnitt int i = line.indexOf("/*"); if (i != -1) { comment = true; line = line.substring(0, i); } i = line.indexOf("//"); if (i != -1) line = line.substring(0, i); } ... Java-Einführungskurs if (line.length() != 0) lines++; } // while System.out.println("File " + theFile.getName() + " has " + lines + " Lines."); bfr.close(); } catch (IOException ioe) { ioe.printStackTrace(); } } } 25 Java-Einführungskurs 26 Ü5.3.3 Lines of Code Ü5.3.3 Lines of Code 3. Modifizieren Sie das gesamte Programm so (Sie dürfen also alle Klassen verändern), so dass ausgehend von einem Startverzeichnis rekursiv alle Java-Dateien (Endung „.java“) auch in allen Unterverzeichnissen untersucht und die Linesof-Code als Gesamtsumme ermittelt werden. • In der Klasse InspectCode, die das Interface implementiert, wird zusätzlich zur Ausgabe der Zeilenanzahl der Wert von lines auch zurückgegeben: public int perform(File theFile) { int lines = 0; ... try { while { ... } } catch (...) { ... } • Um die Aufsummierung zu ermöglichen, soll im Interface ListerCallback die Zeilenanzahl des betrachteten Files an die aufrufende Methode zurückgegeben werden: import java.io.*; return lines; interface ListerCallback { public int perform(File theFile); } Java-Einführungskurs } 27 Java-Einführungskurs Ü5.3.3 Lines of Code Ü5.3.3 Lines of Code • In der doList-Methode der Klasse DirectoryLister • In der main-Methode von DirectoryLister wird die von doList ermittelte Gesamtsumme ausgegeben: • werden die von perform ermittelten Zeilenzahlen aufsummiert • wird die doList-Methode rekursiv für Unterverzeichnisse aufgerufen public int doList(String directory) { File dir = new File(directory); String list[] = dir.list(); 28 public static void main(String args[]) { DirectoryLister dl = new DirectoryLister( new InspectCode()); int result = 0; System.out.println("Result: " + dl.doList(".")); for (int i = 0; i < list.length; i++) { File f = new File(directory + "/" + list[i]); if (!f.isDirectory()) { if (list[i].endsWith(".java")) result = result + lcb.perform(f); } else result = result + doList(directory + "/" + list[i]); } return result; } } Java-Einführungskurs 29 Lehrstuhl für Angewandte Telematik/e-Business Java-Einführungskurs 30 5 29.03.2004 Pause „Take a break... ...have a steaming cup of Java!“ ¨ Java-Einführungskurs 31 Lehrstuhl für Angewandte Telematik/e-Business 6