Sie sind auf Seite 1von 24

Stream-orientierte Dateiverarbeitung

Idee: Dateien oder auch andere Ressourcen werden als „Stromquellen bzw. –
senken“ abstrahiert:

Bildquelle: Oracle

Tran / Hettel GDI 2 1


Stream-orientierte Dateiverarbeitung

Bei der Dateiverarbeitung unterscheidet man zwischen byte-orientierter


und zeichenbasierter Ein- und Ausgabe.
Java stellt hierfür verschiedene Klassen zur Verfügung:
Byteorientiert: InputStream bzw. OutputStream
Zeichenorientiert: Reader bzw. Writer

Bildquelle: Nanyang
University Singapure

Tran / Hettel GDI 2 2


Byte-orientierte Klassen

Bildquelle: Nanyang
University Singapure

Tran / Hettel GDI 2 3


Zeichenorientierte Klassen

Bildquelle: Nanyang
University Singapure

Tran / Hettel GDI 2 4


Stream-orientierte Dateiverarbeitung

Weitere Unterscheidung: buffered und unbuffered Streams.


• Bei unbuffered Streams wird jeder Aufruf einer Lese- oder
Schreibmethode direkt an das Betriebssystem weitergereicht.
• Bei buffered Streams wird in großen Portionen im RAM gehalten. Die
Schreib-Buffers müssen am Ende geflusht werden.

Buffered-Klassen erhält man, in dem man eine entsprechende „Filterklasse“


vor die eigentliche Stream-Klasse schaltet.
Zusätzlich zum Buffer kann noch ein Datenorientierter Filter benutzt
werden, der entsprechende „Convenience“-Methoden besitzt.

Tran / Hettel GDI 2 5


Stream-orientierte Dateiverarbeitung

Bildquelle: Nanyang
University Singapure

Tran / Hettel GDI 2 6


Beispiele: Vorbemerkung

Dateien bzw. Ressourcen müssen nach dem öffnen auch wieder geschlossen
werden.
Typisches Code-Pattern (vor Java 7):

FileInputStream in = null;
try {
in = new FileInputStream(...); // Öffnen des Streams
......
}
catch (IOException ex) {
ex.printStackTrace();
}
finally { // Stream immer schließen
try {
if (in != null) in.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}

Tran / Hettel GDI 2 7


Beispiele: Vorbemerkung

Alles Streams sind „autocloseable“, d.h. implementieren das Interface


AutoCloseable.
Typisches Code-Pattern (ab Java 7):

try( FileInputStream in = new FileInputStream(...) ) // Öffnen des Streams


{
......
}
catch (IOException ex)
{
ex.printStackTrace();
} // Es werden alle im Try geöffneten Ressourcen automatisch geschlossen

Tran / Hettel GDI 2 8


Beispiel 1: Einfaches Kopierprogramm
Byte-orientiertes Kopierprogramm ohne Verwendung von Einlese- bzw.
Schreibpuffer.

try (FileInputStream in = new FileInputStream("Faust1-UTF8.txt");


FileOutputStream out = new FileOutputStream("Faust1-out.txt"))
{
int byteRead;
while ((byteRead = in.read()) != -1)
{
out.write(byteRead);
}
}
catch (IOException ex)
{
ex.printStackTrace();
}

Tran / Hettel GDI 2 9


Beispiel 2: Kopierprogramm
Byte-orientiertes Kopierprogramm mit Verwendung von Einlese- bzw.
Schreibpuffer.
try (
BufferedInputStream in = new BufferedInputStream(
new FileInputStream("Faust1-UTF8.txt"));
BufferedOutputStream out = new BufferedOutputStream(
new FileOutputStream("Faust1-out.txt")) )
{
int byteRead;
while ((byteRead = in.read()) != -1)
{
out.write(byteRead);
}
out.flush();
}
catch (IOException ex)
{
ex.printStackTrace();
}

Tran / Hettel GDI 2 10


Beispiel 3: Kopierprogramm
Zeichenorientiertes Kopierprogramm für Text-Dateien

try (BufferedReader reader = new BufferedReader(


new FileReader("Faust1-UTF8.txt"));
BufferedWriter writer = new BufferedWriter(
new FileWriter("Faust1-out.txt")) )
{
String line;
while ( (line = reader.readLine()) != null )
{
writer.write(line);
writer.newLine();
}
writer.flush();
}
catch (IOException ex)
{
ex.printStackTrace();
}

Tran / Hettel GDI 2 11


PrintStream und Scanner
Häufig wird die Klasse PrintStream verwendet, um Zeichenketten in Datei zu
schreiben. Zum Lesen kommt die Klasse Scanner zum Einsatz:

// Lesen von einer Datei - Hier Zeichen werden eingelesen


try (Scanner in = new Scanner(
new FileReader("src/einigeStandardKlassen/CIODemo.java"));
// Ausgabe in eine Datei mit einem PrintWriter
PrintWriter a = new PrintWriter(
"src/einigeStandardKlassen/CopyOf.java"))
{
while (in.hasNext())
{
String zeile = in.nextLine();
System.out.println(zeile); // Ausgabe auf der Konsole
a.println(zeile); // in die Datei schreiben
}
}

Tran / Hettel GDI 2 12


Speichern bzw. Laden von Objekten

Java erlaubt es, dass Objekte (Instanzen) gespeichert bzw. wieder geladen
(restauriert) werden können.
Das „Speicherlayout“ wird als Byte-Array abgespeichert. Man spricht in
diesem Zusammenhang von Serialisation.
• Zugehörige Klasse muss das Interface Serializable implementieren
Der Mechanismus wird z.B. auch benötigt, um Java-Objekte über ein
Netzwerk zu versenden.

Tran / Hettel GDI 2 13


Beispiel: Speichern eines Objekts
Objekt muss das Interface Serializable implementieren (alle Objektdaten
müssen auch serialisierbar sein)
public class Person implements Serializable
{
private static final long serialVersionUID = 8597830164754364964L;
private String name;
private int alter;

public Person(String name, int alter) {


this.name = name;
this.alter = alter;
}
public String getName() {
return this.name;
}
public int getAlter() {
return this.alter;
}
}

Tran / Hettel GDI 2 14


Beispiel: Speichern eines Objekts
Objekt wird mit Hilfe eines ObjectOutputStreams gespeichert

Person p = new Person("Hans-Otto", 42);

try (ObjectOutputStream out = new ObjectOutputStream(


new BufferedOutputStream(new FileOutputStream("person.ser"))))
{
out.writeObject(p); // Objekt in Datei ablegen
out.flush();
}
catch (IOException exce)
{
exce.printStackTrace();
}

Tran / Hettel GDI 2 15


Beispiel: Laden eines Objekts

try (ObjectInputStream in = new ObjectInputStream(


new BufferedInputStream(new FileInputStream("person.ser"))) )
{
Person p = (Person) in.readObject(); // Objekt aus Datei laden

System.out.println( p.getName() + " " + p.getAlter() );


}
catch (IOException | ClassNotFoundException exce)
{
exce.printStackTrace();
}

Tran / Hettel GDI 2 16


Das Arbeiten mit Dateien (ab JDK 1.7)

Mit dem JDK 7 wurde das Arbeiten mit Dateien grundlegend überarbeitet
und hierzu die Klasse java.nio.file.Files eingeführt.
In der „alten“ Klasse java.io.File ist das Konzept eines Dateisystems nur
unzureichend umgesetzt.

Tran / Hettel GDI 2 17


Die Klasse Files (ab JDK 1.7)

Mit dem JDK 1.7 wurde die Klasse Files (Package: java.nio.file) die
Path-Klasse eingeführt.

Path path = Paths.get("C:\\Work\\Vorlesungen\\Prog1\\Stand.txt");


// Unix/Mac
// Path path = Paths.get("/work/vorlesungen/prog1/stand.java");

System.out.println("toString: " + path.toString());


System.out.println("getFileName: " + path.getFileName());
System.out.println("getParent: " + path.getParent());
System.out.println("getRoot: " + path.getRoot());

int nameCount = path.getNameCount();


System.out.println("getNameCount: " + nameCount);
for (int i = 0; i < nameCount; i++)
{
System.out.println("getName(" + i + "): " + path.getName(i));
}

Tran / Hettel GDI 2 18


Die Klasse Files (ab JDK 1.7)

Einige Methoden der Klasse Files


Methoden zum Anlegen, Löschen bzw. Verschieben von Dateien
Verschiedene Abfragemethoden.
• Eine Methoden haben als zweites Argument LinkOptionen wie z.B.
LinkOption.NOFOLLOW_LINKS.

public static long size(Path path)


public static boolean exists(Path path, LinkOption... options)
public static boolean notExists(Path path, LinkOption... options)
public static boolean isDirectory(Path path, LinkOption... options)
public static boolean isRegularFile(Path path, LinkOption... options)
public static boolean isSymbolicLink(Path path)
public static boolean isReadable(Path path)
public static boolean isWritable(Path path)
public static boolean isExecutable(Path path)
...
...

Tran / Hettel GDI 2 19


Die Klasse Files (ab JDK 1.7)

Unterschied zwischen den java.io- und java.nio-Klassen.

Bildquelle:
http://tutorials.jenkov.com
Tran / Hettel GDI 2 20
Beispiel: Kopierprogramm (1)

try
{
Path input = Paths.get("Faust1-UTF8.txt");
Path output = Paths.get("Faust1-out.txt");

List<String> lines = Files.readAllLines(input);


Files.write( output, lines );
}
catch (IOException exce)
{
exce.printStackTrace();
}

Tran / Hettel GDI 2 21


Beispiel: Kopierprogramm (2)

try
{
Path input = Paths.get("Faust1-UTF8.txt");
Path output = Paths.get("Faust1-out.txt");

Files.copy( input, output, StandardCopyOption.REPLACE_EXISTING );


}
catch (IOException exce)
{
exce.printStackTrace();
}

Tran / Hettel GDI 2 22


Zugriff auf Web-Ressourcen

Klassen: URL und HttpURLConnection


Mit Hilfe dieser Klassen kann man auf Web-Ressourcen zugreifen
Beispiel
URL url = new URL("http://escher.informatik.hs-kl.de/jtrainer/");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setUseCaches(false);

// Mit
// connection.addRequestProperty( key, value )
// können weitere Attribute gesetzt werden

Tran / Hettel GDI 2 23


Zugriff auf Web-Ressourcen

...

// Get Response
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
StringBuilder response = new StringBuilder();
String line;
while ((line = rd.readLine()) != null)
{
response.append(line);
response.append(System.lineSeparator());
}
rd.close();
connection.disconnect();
System.out.println(response.toString());

Tran / Hettel GDI 2 24