Ein- und Ausgabe SYSTEM SOFTWARE 1 Streaming Streams Readers und Writers Objektserialisierung Dateien NIO Zusammenfassung SYSTEM SOFTWARE 2 Streaming Ein/Ausgabe und Fluss von Daten Daten werden nicht auf einmal übertragen, sondern fließen in einem kontinuierlichen Prozess Datenquellen – Input – Output – Datensenken Eingabestrom verbindet Datenquelle mit Programm Ausgabestrom verbindet Programm mit Datensenke Streams abstrahieren von konkreten Quellen und Senken Terminal- oder Konsolenfenster Dateien Client- und Serverprogramme … InputStream Programm Daten quelle OutputStream Daten senke SYSTEM SOFTWARE 3 Streaming in Java Paket java.io Byteorientierte Ein- und Ausgabe Zeichenorientierte Ein- und Ausgabe 2 Arten von Streams Byte-Streams: byte-weises Lesen und Schreiben InputStream- und OutputStream-Klassen Char-Streams: zeichenweises Lesen und Schreiben (Unicode) Reader- und Writer-Klassen SYSTEM SOFTWARE 4 Basisklasse InputStream abstrakte Basisimplementierung, von der konkrete InputStreams abgeleitetet werden abstrakte Methode read(), die ein Zeichen liest konkrete Implementierungen aller anderen Methoden Methoden arbeiten synchron, d.h. blockieren, solange bis Operation abgeschlossen Methoden werfen IOExceptions, wenn etwas schief geht public abstract class InputStream { public abstract int read() throws IOException public int read(byte b[]) throws IOException public int read(byte b[], int off, int len) throws IOException public long skip(long n) throws IOException public int available() throws IOException public void close() throws IOException public synchronized void mark(int readlimit) public synchronized void reset() throws IOException public boolean markSupported() } SYSTEM SOFTWARE 5 Basisklasse OutputStream abstrakte Basisimplementierung, von der konkrete OutputStreams abgeleitetet werden abstrakte Methode write(), die ein einzelnes Zeichen schreibt konkrete Implementierungen aller anderen Methoden Methoden arbeiten synchron, d.h. blockieren, solange bis Operation abgeschlossen Methoden werfen IOExceptions, wenn etwas schief geht public abstract class OutputStream { public abstract void write(int b) throws IOException; public void write(byte b[]) throws IOException public void write(byte b[], int off, int len) throws IOException public void flush() throws IOException public void close() throws IOException } public class IOException extends Exception { public IOException() public IOException(String s) } SYSTEM SOFTWARE 6 Realisierung von konkreten Stream-Klassen Ableiten von InputStream bzw. OutputStream Überschreiben der abstrakten Methoden read bzw. write Z.B.: FileInputStream: Lesen von Dateien public class FileInputStream extends InputStream { public FileInputStream(String name) throws FileNotFoundException public FileInputStream(File file) throws FileNotFoundException public native int read() throws IOException … } native implementiert! Z.B.: FileOutputStream: Schreiben auf Dateien public class FileOutputStream extends OutputStream { public FileOutputStream(String name) throws FileNotFoundException public FileOutputStream(String name, boolean append) throws FileNotFoundException public FileOutputStream(File file) throws FileNotFoundException public native void write(int b) throws IOException … } native implementiert! SYSTEM SOFTWARE 7 Beispiel: Kopieren einer Datei static void copyFile(String ifile, String ofile) { InputStream in = null; OutputStream out = null; try { in = new FileInputStream(ifile); out = new FileOutputStream(ofile); int b = in.read(); Man beachte das Abfangen while (b >= 0) { der Exceptions out.write(b); b = in.read(); } } catch (FileNotFoundException e) { System.out.println("File does not exist"); } catch (IOException e) { System.out.println("Error in reading or writing file"); } finally { if (in != null) { try { in.close(); } catch (IOException ioe) {} } if (out != null) { try { out.close(); } catch (IOException ioe) {} } } und Schließen der Streams!! } SYSTEM SOFTWARE 8 try-with-resources try-Anweisung mit Resource-Management Erzeugen / Öffnen der Resource Verarbeitung automatisches Schließen Resources müssen AutoClosable implementieren try ( **** Create resources here **** ) { **** user resources here **** } catch ( **** some exceptions **** e) { ... } SYSTEM SOFTWARE Resources automatisch geschlossen 9 Beispiel: Kopieren einer Datei Varianten mit try-Anweisung mit Resource-Management static void copyFile_WithResources(String ifile, String ofile) { try ( InputStream in = new FileInputStream(ifile); OutputStream out = new FileOutputStream(ofile) ) { int b = in.read(); while (b >= 0) { out.write(b); b = in.read(); } Schließen der Streams } catch (FileNotFoundException e) { automatisch !! System.out.println("File does not exist"); } catch (IOException e) { System.out.println("Error in reading or writing file"); } } SYSTEM SOFTWARE 10 Filter-Streams: Überlagern von Streams FilterStreams sind Streams, die auf einem anderen Stream aufbauen Ketten von Streams bilden, um Basisstreams mit weiterer Funktionalität anzureichern Höhere Schnittstellen zur Verfügung zu stellen Input Stream Filter Input Stream Filter Input Stream Prgm Filter Output Stream Filter Output Output Stream Stream Daten senke Daten quelle InputStream fin = new FileInputStream("input.txt"); BufferedInputStream bin = new BufferedInputStream(fin); DataInputStream din = new DataInputStream(bin); OutputStream fout = new FileOutputStream("output.txt"); BufferedOutputStream bout = new BufferedOutputStream(fout); DataOutputStream dout = new DataOutputStream(bout); SYSTEM SOFTWARE 11 FilterStreams: BufferedInputStream - BufferedOutputStream Gepufferte Eingabe: BufferedInputStream Effizienz durch Vorauslesen File ifile = new File(“inputfile.txt”); InputStream in = new BufferedInputStream( new FileInputStream(ifile)); Gepufferte Ausgabe: BufferedOutputStream Effizienz durch verzögertes Schreiben Tatsächliche Ausgabe erst wenn Puffer voll Methode flush erzwingt Ausgabe des Puffers File ofile = new File(“outputfile.txt”); OutputStream out = new BufferedOutputStream( new FileOutputStream(ofile)); SYSTEM SOFTWARE 12 FilterStreams: DataInputStream, DataOutputStream Ausgabe primitiver Datentypen public class DataOutputStream extends FilterOutputStream { void writeBoolean(boolean v); void writeByte(int v); void writeBytes(String s); void writeChar(int v); void writeChars(String s); void writeDouble(double v); void writeFloat(float v); void writeInt(int v); void writeLong(long v); void writeShort(int v); void writeUTF(String str); ... } public class DataInputStream extends FilterInputStream { boolean readBoolean(); byte readByte(); char readChar(); double readDouble(); float readFloat(); int readInt(); long readLong(); short readShort(); int readUnsignedByte(); int readUnsignedShort(); String readUTF(); ... } File fout = new File("output.data"); DataOutputStream out = new DataOutputStream( new FileOutputStream(fout)); out.writeDouble(Math.PI); out.close(); SYSTEM SOFTWARE output: 0x40 0x09 0x21 0xfb 0x54 0x44 0x2d 0x18 ; ; @.!û TD-. 13 InputStream Klassenhierarchie Auszug! PipedInputStream BufferedInputStream SequenceInputStream InputStream CheckedInputStream FileInputStream DigestInputStream FilterInputStream ZipInput Stream JarInput Stream InflaterInputStream StringBufferInputStream LineInputStream GZIPInput Stream ByteArrayInputStream PushBackInputStream ObjectInputStream DataInputStream <<interface>> ObjectInput <<interface>> DataInput SYSTEM SOFTWARE 14 OutputStream Klassenhierarchie Auszug! PipedOutputStream BufferedOutputStream OutputStream FileOutputStream CheckedOutputStream DigestOutputStream FilterOutputStream ZipOutput Stream JarOutput Stream DeflaterOutputStream ByteArrayOutputStream PrintStream GZIPOutput Stream DataOutputStream ObjectOutputStream <<interface>> ObjectOutput <<interface>> DataOutput SYSTEM SOFTWARE 15 Diverse Streamklassen public class PipedOutputStream extends OutputStream { void connect(PipedInputStream snk); ... } • Realisierung von Pipes public class PipedInputStream extends InputStream { void connect(PipedOutputStream src); ... } public class PushbackInputStream extends InputStream { int read(); void unread(int b); ... } • unterstützt Zurückschreiben (unread) public class PrintStream extends FilterOutputStream { public void print(boolean b) public void print(int b) … public void println(boolean b) … } • formatierte Ausgabe von Daten • mittels print und printlnMethoden SYSTEM SOFTWARE 16 Standardstreams Streams in der Klasse System static InputStream in; static PrintStream out; static PrintStream err; // the standard input stream // the standard output stream // the standard error stream Filtern der Standardstreams BufferedReader input = new BufferedReader( new InputStreamReader(System.in)); String line = input.readLine(); Umleiten der Standardstreams java Foo < input.txt > output.txt 2> error.txt oder java Foo > output.txt 2>&1 oder java Foo >> output.txt SYSTEM SOFTWARE 17 Hierarchie der Ausnahmen Auszug! Exception ClassNotFoundException IOException FileNotFoundException EOFException ObjectStreamException NotSerializableException SYSTEM SOFTWARE 18 Streaming Streams Readers und Writers Objektserialisierung Dateien NIO Zusammenfassung SYSTEM SOFTWARE 19 Zeichenorientierte Ein- und Ausgabe Ein- und Ausgabe von char-Daten über Readers und Writers Basisklassen Reader (abstrakte Basisklasse analog zu InputStream) Writer (abstrakte Basisklasse analog zu OutputStream) Datenkonvertierung Abbildung von Zeichen auf Bytes erforderlich (Dateien sind byteorientiert) FileReader und FileWriter verwenden Standardcodierung Andere Codierungen mittels InputStreamReader und OutputStreamWriter bzw. Character Sets Writer out = new OutputStreamWriter( new FileOutputStream("fname"), "UTF8" // encoding parameter ); SYSTEM SOFTWARE 20 Basisklasse Reader Abstrakte Basisimplementierung, von der konkrete Reader abgeleitetet werden Abstrakte Methode read(char[] cbuf, int off, int len) welche einen char-Array schreibt Andere Methoden bauen auf dieser auf public abstract class Reader { public int read() throws IOException public int read(char[] cbuf) throws IOException public abstract int read(char[] cbuf, int off, int len) throws IOException public long skip(long n) throws IOException public boolean ready() throws IOException public synchronized void mark(int readlimit) public synchronized void reset() throws IOException public boolean markSupported() public abstract void close() throws IOException } SYSTEM SOFTWARE 21 Basisklasse Writer Abstrakte Basisimplementierung, von der konkrete Writer abgeleitetet werden Abstrakte Methode write(char[] cbuf, int off, int len) welche einen char-Array füllt Andere Methoden bauen auf dieser auf public abstract class Writer { public void write(int c) throws IOException public void write(char[] cbuf) throws IOException public abstract void write(char[] cbuf, int off, int len) throws IOException public void write(String str) throws IOException public void write(String str, int off, int len) throws IOException public abstract void flush() throws IOException public abstract void close() throws IOException } SYSTEM SOFTWARE 22 BufferedReader - PrintWriter Zeilenweises lesen mit readLine String line; BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); try { line = reader.readLine(); } catch (IOException ioe) { ioe.printStackTrace(); } Schreiben mit print PrintWriter writer = new PrintWriter(new OutputStreamWriter(System.out)); try { writer.println(line); writer.flush(); } catch (IOException ioe) { ioe.printStackTrace(); } SYSTEM SOFTWARE 23 Reader Klassenhierarchie Auszug! PipedReader Reader InputStreamReader FileReader FilterReader PushbackReader StringReader CharArrayReader BufferedReader SYSTEM SOFTWARE LineNumberReader 24 Diverse Reader public class InputStreamReader extends Reader{ public InputStreamReader(InputStream in) ... } • Brücke zu InputStream public class LineNumberReader extends Reader { int getLineNumber(); ... } • Zugriff auf Zeilennummern public class BufferedReader extends Reader { public String readLine() throws IOException ... } • gepufferte Eingabe • unterstützt zeilenweises Lesen (readLine) public class PushbackReader extends Reader { public void unread(char[] cbuf, int off, int len) throws IOException ... } • unterstützt Zurückschreiben (unread) public class PipedReader extends Reader { public void connect(PipedWriter src) throws IOException … } • Realisierung von Pipes • in Kombination mit PipedWriter SYSTEM SOFTWARE 25 Writer Klassenhierarchie Auszug! PipedWriter OutputStreamWriter Writer FileWriter FilterWriter StringWriter CharArrayWriter BufferedWriter PrintWriter SYSTEM SOFTWARE 26 Diverse Writer public class OutputStreamWriter extends Writer • Brücke zu OutputStream public OutputStreamWriter (OutputStream out) ... } public class PrintWriter extends Writer { public void print(boolean b) public void print(int b) … public void println(boolean b) … } public class BufferedWriter extends Writer { public void newLine() throws IOException public void flush() throws IOException ... } public class PipedWriter extends Writer { public void connect(PipedReader snk) throws IOException … } SYSTEM SOFTWARE • formatierte Ausgabe von Daten als Text • mittels print und printlnMethoden • gepufferte Ausgabe • unterstützt neue Zeile (newLine) • Realisierung von Pipes • in Kombination mit PipedReader 27 Streaming Streams Readers und Writers Objektserialisierung Dateien NIO Zusammenfassung SYSTEM SOFTWARE 28 Serialisierung von Objekten Speichern des Zustands von Objekten Plattformunabhängige Transformation in Bytes Verwendung für Speicherng von Objekten, Kommunikation von Programmen Serialisierung Klasse muss Serializable implementieren Automatische Serialisierung der Felder Transitive Hülle Objekte die über Referenzen in Feldern erreichbar sind, werden ebenfalls serialisiert in Form eines Objektgraphen (und nicht eines Baums) Keine Serialisierung „transienter“ Felder public class ObjectOutputStream { void writeBoolean(boolean data); ... void writeObject(Object obj); } ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data")); Person p = ...; out.writeObject(p); SYSTEM SOFTWARE 29 Serializable Nur Objekte, die Serializable implementieren, können serialisiert werden Damit werden alle Felder, die serialisierbar sind, automatisch mit dem Objekt serialisiert Felder mit Basisdatentypen Felder mit Typen, die serialisierbar sind Kennzeichnet man Felder mit transient, werden diese nicht serialisiert !! Verhinderung der Serialisierung von bestimmten Werten Felder mit Werte, die nicht serialisierbar sind, müssen transient markiert werden sonst NotSerializableException public interface Serializable { } public class Person implements Serializable { private String name; private int age; private List<Person> children; private transient List<PropertyChangeListener> listener; } SYSTEM SOFTWARE 30 Serialisierbare / Nicht-serialisierbare Datentypen Serialisierbar: Basisdatentypen (int, boolean, double, …) Alle Arrays String Collections: ArrayList, LinkedList, TreeSet, … Calendar, Date, etc. Alle weiteren Typen, die Serializable implementieren Beispiel nicht serialisierbarer Werte: Thread, ClassLoader, etc. Objekte der Java-VM InputStream, Socket, etc. Objekte, die auf Betriebssystemressourcen zugreifen und andere SYSTEM SOFTWARE 31 Serialisierung von Objektgraphen Kunde Name = Max Bank Konto Konto Name = SSW Konten Betrag = € 100 Besitzer Next Betrag = € 500 Besitzer Next Mehrere Referenzen auf das selbe Objekt: 1. Besuch: Objekt vollständig schreiben weiterer Besuch: nur ID des Objekts schreiben (Bank) "SSW" (Konto) € 100 (Kunde) "Max" SYSTEM SOFTWARE (Konto) € 500 (Kunde) 878 32 Deserialisierung Einlesen eines Objekts Allokation von Speicher und Initialisierung ClassNotFoundException falls Klasse nicht vorhanden Einlesen des Objekts Transiente Felder erhalten Standardwert public class ObjectInputStream { boolean readBoolean(); byte readByte(); ... Object readObject(); ... } ObjectInputStream in = new ObjectInputStream(new FileInputStream("data")); Person p = (Person) in.readObject(); SYSTEM SOFTWARE 33 Serialisierungsformat public class Person implements Serializable { private String name; private int age; } Serialisierung enthält vollständige Typinformation Versionsnummer Person hans = new Person("Hans", 26); Daten AC 73 72 EB 00 L 74 I 78 70 74 00 ED 00 A3 02 00 00 00 00 05 06 Person AE 56 EF 40 EE 9B 02 04 name 12 Ljava/lang/String 03 age 00 04 Hans 00 00 00 00 1A Dateikennzeicheb und Version der Serialisierung 73 für neues Objekt 72 für Klasse, Länge des Klassennamens, Klassenname Serial UID, Flag für implements Serializable Anzahl der Felder L für Feldtyp Klasse, Länge Feldnamen, Feldname 74 für Typbezeichner, Länge Typname, Typename I für Feldtyp int, Länge Typname, Typename 78 Ende der Feldbeschreibungen 70 Keine Superklasse Daten Feld name 3 Byte Daten für Feld age SYSTEM SOFTWARE 34 Benutzerdefinierte Serialisierung (1/3) Anpassung der Serialisierung durch Implementierung von Methoden writeObject und readObject private void writeObject(ObjectOutputStream stream) throws IOException; private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException; class LabeledPoint implements Serializable { private String label; private transient Point2D.Double point; ... private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); out.writeDouble(point.x); out.writeDouble(point.y); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); double x = in.readDouble(); double y = in.readDouble(); point = new Point2D.Double(x, y); } } SYSTEM SOFTWARE Point2D nicht serialisierbar transient Standard-Serialisierung aller anderen Felder inkl. Superklasse Serialisierung der Daten des transienten Feldes Standard-Deserialisierung Deserialisierung der Daten des transienten Feldes Rekonstruktion des transienten Feldes 35 Benutzerdefinierte Serialisierung (2/3) Eigene Serialisierung durch Implementierung des Interfaces Externalizable public interface Externalizable extends java.io.Serializable { void writeExternal(ObjectOutput out) throws IOException; void readExternal(ObjectInput in) throws IOException,ClassNotFoundException; } Serialisierung muss vollständig implementiert werden Nur Identität der Klasse wird automatisch gespeichert Verwendet und fordert Standard-Konstruktor (ohne Parameter) class LabeledPoint implements Externalizable { ... public LabeledPoint() { } Standard-Konstruktor gefordert public void writeExternal(ObjectOutput out) throws IOException { out.writeUTF(label); Schreiben der Daten in out.writeDouble(point.x); out.writeDouble(point.y); writeExternal } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { label = in.readUTF(); double x = in.readDouble(); double y = in.readDouble(); point = new Point2D.Double(x, y); } Lesen der Daten und Setzen der Felder } SYSTEM SOFTWARE 36 Benutzerdefinierte Serialisierung (3/3) Ersetzen durch ein anderes Objekt: writeReplace und readResolv ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException; ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException; writeReplace wird vor dem Schreiben aufgerufen readResolve wird nach dem Lesen aufgerufen Beispiel: Lesen von Objekten und Ersetzen durch Singleton-Objekt class Orientation implements Serializable { public static final Orientation HORIZONTAL = new Orientation(1); public static final Orientation VERTICAL = new Orientation(2); private int value; private Orientation(int value) { this.value = value; } protected Object readResolve() throws ObjectStreamException { if (value == 1) return Orientation.HORIZONTAL; if (value == 2) return Orientation.VERTICAL; Nach Deserialisierung des Objekts return null; wird Singleton-Objekt zurückgegeben! } } Achtung: Serialisierung von Enum-Werten funktioniert automatisch!! SYSTEM SOFTWARE 37 Versionsverwaltung (1/2) Problem: Kompatibilität von serialisierten Objekten mit neuen Versionen von Klassen bei Serialisierung wird mit Klasse eindeutige UID gespeichert Hash-Code (SHA) aus Klassendefinition Ändert sich Klasse, wird beim Lesen Objekt als inkompatibel erkannt Objekt kann nicht mehr gelesen werden! Oft ist aber eine neue Klasse kompatibel zur alten Version, weil z.B. nur Methoden und keine Felder verändert wurden SYSTEM SOFTWARE 38 Versionsverwaltung (2/2) Abhilfe: Durch Setzen der serialVersionUID im Quellcode wird bei Serialisierung UID nicht mehr berechnet sondern die Nummer aus Quellcode entnommen Vorgehen: Bestimmen der UID der alten Version mit Tool serialver Setzen der gleichen UID als serialVersionUID in Quellcode der neuen Version public class Person implements Serializable { private static final long serialVersionUID = 213554356225514906L; … Damit wird neue Version als kompatibel zur alten Version erkannt Eventuell spezifische Lesemethoden (readExternal), um neue Objekte aus alten serialisierten Daten zu erzeugen SYSTEM SOFTWARE 39 Streaming Streams Readers und Writers Objektserialisierung Dateien NIO Zusammenfassung SYSTEM SOFTWARE 40 File Abstrakte Repräsentation einer Datei oder eines Verzeichnisses Konstruktor greift noch nicht auf Dateisystem zu Definiert plattformspezifische Trennzeichen separator und pathSeparator Erzeugen von Dateiströmen Mittels Dateinamen oder File-Objekt public class File { boolean canRead(); boolean canWrite(); boolean delete(); boolean exists(); String getName() boolean isDirectory(); boolean isFile(); long lastModified(); long length(); String[] list(); File[] listFiles(); ... } static long totalSize(File dir) { if (!dir.isDirectory()) { return -1; } long size = 0; File[] files = dir.listFiles(); for (int i = 0; i < files.length; i++) { size += files[i].length(); } return size; } SYSTEM SOFTWARE 41 Streaming Streams Readers und Writers Objektserialisierung Dateien NIO Zusammenfassung SYSTEM SOFTWARE 42 NIO Mit NIO und NIO.2 gibt es neue Klassen für Dateimanagement und Dateiein- und ausgabe Packages java.nio.files Path und Files für Dateimanagement java.nio.channel Channels für gepufferte und asynchrone Ein/Ausgabe java.nio.charset Charset für Kodierung von Unicode SYSTEM SOFTWARE 43 Path (1/2) Path ist Klasse für Dateipfade repräsentiert einen Pfad (und noch keine Datei) stellt Methoden für die Manipulation von Pfaden dar Paths mit statischen Methoden get, um Pfad zu erstellen private static final String SRC = "C:\\Users\\hp\\Java\\src"; Path srcPath = Paths.get(SRC); Path nioRelPath = Paths.get("nio"); Path javaFilePath = Paths.get(SRC, "nio", "PathDemo.java"); absoluter Pfad relativer Pfad Path stellt dann Methoden für den Umgang mit Pfaden bereit resolve: neuer Pfad aus this und (relativem) Argumentpfad Path nioAbsPath = srcPath.resolve(nioRelPath); relativize: relativer Pfad um von this zum this und (relativer) anderer Path javaRelPath = srcPath.relativize(javaFilePath); normalize: eliminiert redundante Teilpfade Path homePath = Paths.get("C:\\Users\\hp\\..\\..\\Users\\hp"); Path homePathNorm = homePath.normalize(); SYSTEM SOFTWARE 44 Path (2/2) Zugriff auf Teile eines Pfades über Iterator C:\ Users hp Java nio PathDemo.java for (Path p : javaFilePath) { println(p); } oder mit indiziertem Zugriff javaFilePath.get(0)); C:\ letzter Teil (Datei- oder Verzeichnisname) println(javaFilePath.getFileName()); PathDemo.java Zugriff auf Eigenschaften println(thisFilePath.endsWith("PathDemo.java")); println(thisFilePath.startsWith("C:\\")); true true uvm. SYSTEM SOFTWARE 45 Files (1/3) Files mit statischen Methoden, um auf Dateisystem zuzugreifen und Dateien zu manipulieren Abfrage, ob Datei oder Verzeichnis mit Pfad existiert und Erzeugen if (! Files.exists(javaFilePath)) { Files.createFile(javaFilePath); } if (! Files.exists(nioPath)) { Files.createDirectory(nioPath); } Dateien kopieren, verschieben, löschen beliebig viele Options ! Files.copy(javaFilePath, javaCopyPath, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); Files.move(javaFilePath, javaCopyPath, StandardCopyOption.REPLACE_EXISTING); Files.delete(javaFilePath); Files.deleteIfExists(javaFilePath); SYSTEM SOFTWARE 46 Files (2/3) Files lesen und schreiben lines Files.lines(javaFilePath).forEach(line -> { println(line); }); Stream-Zugriff ist lazy! realdAllLines List<String> lines = Files.readAllLines(javaFilePath); for (String line : lines) { println(line); } Zugriff auf Input/Outputstreams BufferedReader r = Files.newBufferedReader(javaFilePath); BufferedWriter w = Files.newBufferedWriter(javaFilePath); SYSTEM SOFTWARE 47 Files (3/3) Zugriff auf Attribute beliebig viele Options ! FileTime lastModified = Files.getLastModifiedTime(javaFilePath); println(lastModified); 2016-04-10T09:11:23.131982Z long size = (long)Files.getAttribute(javaFilePath, "size"); println(size); FileTime now = FileTime.fromMillis(System.currentTimeMillis()); Files.setLastModifiedTime(javaFilePath, now); Zugriff auf alle Attribute ! BasicFileAttributeView Attribute Name "lastModifiedTime" "lastAccessTime" "creationTime" "size" "isRegularFile" "isDirectory" "isSymbolicLink" "isOther" "fileKey" Type FileTime FileTime FileTime Long Boolean Boolean Boolean Boolean Object BasicFileAttributeView attrs = Files.getFileAttributeView(javaFilePath, BasicFileAttributeView.class); attrs.setTimes(now, now, now); SYSTEM SOFTWARE 48 Iteration über Files walk: Stream von Pfaden eines Verzeichnisses Path root = Paths.get(SRC); try (Stream<Path> paths = Files.walk(root, 3)) { paths.forEach(p -> { println(p.toString()); }); Stream erzeugen als closable Ressource ! Zugriff auf Stream lazy ! } C:\Users\hp\Java C:\Users\hp\Java\nio C:\Users\hp\Java\nio\FileDemo.java ... PathMatcher: Suchen von Files über Glob PathMatcher javaMatcher = FileSystems.getDefault().getPathMatcher("glob:**.java"); if (javaMatcher.matches(javaFilePath)) println("It‘s a Java file"); PathMatcher javaMatcher = FileSystems.getDefault().getPathMatcher("glob:**.java"); try (Stream<Path> paths = Files.walk(root)) { paths.forEach(p -> { if (javaMatcher.matches(p)) { println(p.toString()); } }); } SYSTEM SOFTWARE 49 Walk über Verzeichnisbaum walkFileTree: Visitor über Verzeichnisbaum public interface FileVisitor<T> { FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs) throws IOException; FileVisitResult visitFile(T file, BasicFileAttributes attrs) throws IOException; FileVisitResult visitFileFailed(T file, IOException exc) throws IOException; FileVisitResult postVisitDirectory(T dir, IOException exc) throws IOException; } Files.walkFileTree(root, new FileVisitor<Path>() { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { printfln(indent + "START %s ------", dir.toString()); return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { printfln(indent + "FILE %s", file.toString()); return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { printfln(indent + "++ FAILED %s", file.toString()); return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { printfln(indent + "END %s --------", dir.toString()); return FileVisitResult.CONTINUE; } }); SYSTEM SOFTWARE 50 WatchService (1/3) Beobachten Änderungen in Verzeichnis WatchService watcher = FileSystems.getDefault().newWatchService(); FileWatcher für FileSystem erzeugen ! Path root = Paths.get(SRC); try (Stream<Path> paths = Files.walk(root)) { paths.forEach(p -> { if (Files.isDirectory(p)) { try { p.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); } catch (Exception e) { } Verzeichnis beim Watcher } registrieren }); } ... SYSTEM SOFTWARE 51 WatchService (2/3) Beobachten Änderungen in Verzeichnissen watcherThread = new Thread( () -> { in eigenem Thread while (! stopWatcher) { try { WatchKey zugreifen blockierend! WatchKey k = watcher.take(); for (WatchEvent<?> evt: k.pollEvents()) { WatchEvent<Path> pevt = (WatchEvent<Path>) evt; Über Events iterieren Path relPath = pevt.context(); Path dir = (Path)k.watchable(); Path absPath = dir.resolve(relPath); Events behandeln printfln("CHANGE %s:", pevt.kind().toString()); printfln(" dir: %s", dir.toString()); printfln(" relative: %s, absolute: %s", relPath.toString(), absPath.toString()); if (Files.isDirectory(absPath)) { if (pevt.kind() == ENTRY_CREATE) { try { absPath.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); } catch (Exception e) { neues Verzeichnis beim Watcher } registrieren } } } k.reset(); nach Behandlung WatchKey reseten (sonst nur } catch (InterruptedException e) { einmal pro Registrierung aktiv) } } }); watcherThread.start(); SYSTEM SOFTWARE 52 WatchService (3/3) Zusammenfassung der Zugriffe Erzeugen eines FileWatchers global für FileSystem WatchService watcher = FileSystems.getDefault().newWatchService(); Registrieren von Verzeichnis dirPath.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); Warten und Zugriff auf Änderungen WatchKey WatchKey k = watcher.take(); WatchKey erlaubt Zugriff auf Ereignisse Ereignisse und Pfad des Ereignises for (WatchEvent<?> evt: k.pollEvents()) { WatchEvent<Path> pevt = (WatchEvent<Path>) evt; Path relPath = pevt.context(); Verzeichnis, in dem Ereignis aufgetreten ist Path dir = (Path)k.watchable(); Reset des WatchKey, wenn Verzeichnis weiter beobachtet werden soll k.reset(); oder cancel, wenn nicht k.cancel(); SYSTEM SOFTWARE 53 Character Sets in java.nio.charset Charset Klasse für Character-Kodierung Erzeugen eines Charset-Objekts mit statischer Methode forName und Namen der Kodierung Charset cset = Charset.forName("UTF-8"); Kodierung mit ByteBuffers String original = "..."; ByteBuffer buffer = cset.encode(original); byte[] bytes = buffer.array(); Decodierung über ByteBuffers und CharBuffers ByteBuffer bbuf = ByteBuffer.wrap(bytes); CharBuffer cbuf = cset.decode(bbuf); String decoded = cbuf.toString(); Verwendung von Charset bei Reader und Writer Writer out = new OutputStreamWriter(new FileOutputStream("fname.txt"), cset); Reader in = new InputStreamReader(new FileInputStream("fname.txt"), cset); SYSTEM SOFTWARE 54 Streaming Streams Readers und Writers Objektserialisierung Dateien NIO Zusammenfassung SYSTEM SOFTWARE 55 Zusammenfassung Datenströme Verbinden Datenquelle mit Programm oder Programm mit Datensenke Byteorientierte Datenströme InputStream und OutputStream FileInputStream und FileOutputStream Zeichenorientierte Datenströme Reader und Writer Gepufferte Datenströme BufferedInputStream und BufferedOutputStream BufferedReader und BufferedWriter Serialisierung Plattformunabhängige Transformation des Objektgraphen in Bytes NIO Neue mächtige Konzepte für Dateimanagement und Ein/Ausgabe SYSTEM SOFTWARE 56