io-streams

IO - Streams


Schließen von Resourcen

String readFirstLineFromFile(String filename) throws IOException {
    BufferedReader reader = new BufferedReader(
            new FileReader(filename));
    try {
        return reader.readLine();
    } finally {
        reader.close();
    }
}

oder besser

String readFirstLineFromFile(String filename) throws IOException {
    try (BufferedReader reader = new BufferedReader(
            new FileReader(filename))) {
        return reader.readLine();
    }
}

try-with

  1. Autoclosable implementieren
  2. try-with führt close aus
class Resource implements AutoCloseable {

    @Override
    public void close() throws IOException {
        System.out.println("closed");
    }
}

auch mehrere

try (Resource resource = new Resource();
     OtherResource another = new OtherResource()) {
    // Verwendung
}   // Ausgabe "close"

Motivation

public class Student {

    private int id;
    private String name;
    private School school;

    ...
}
School htl = new School("HTL");
Student student = new Student(42, "Bob", htl);

student speichern/senden


Text

<Student>
  <id>42</id>
  <name>Bob</name>
  <school>
    <name>HTL</name>
  </school>
</Student>
{
  "id": 42,
  "name": "Bob",
  "school": {
    "name": "HTL"
  }
}
--&hyphen;
id: 42
name: "Bob"
school:
  name: "HTL"

Binär

AC ED 00 05 73 72 00 1A 73 65 72 69
61 6C 69 7A 69 6E 67 2E 64 6F 6D 61
69 6E 2E 53 74 75 64 65 6E 74 0E C3
4C D7 CF 32 96 43 02 00 03 49 00 02
69 64 4C 00 04 6E 61 6D 65 74 00 12
4C 6A 61 76 61 2F 6C 61 6E 67 2F 53
74 72 69 6E 67 3B 4C 00 06 73 63 68
6F 6F 6C 74 00 1B 4C 73 65 72 69 61
6C 69 7A 69 6E 67 2F 64 6F 6D 61 69
6E 2F 53 63 68 6F 6F 6C 3B 78 70 00
00 00 2A 74 00 03 42 6F 62 73 72 00
19 73 65 72 69 61 6C 69 7A 69 6E 67
2E 64 6F 6D 61 69 6E 2E 53 63 68 6F
6F 6C 74 4C D2 E9 49 ED 86 3D 02 00
01 4C 00 04 6E 61 6D 65 71 00 7E 00
01 78 70 74 00 03 48 54 4C

overview


Überblick

Lesen Schreiben
bytes %InputStream %OutputStream
chars %Reader %Writer
Files Files. Files.

Bytestreams

public abstract class OutputStream implements Closeable, Flushable {

    public abstract void write(int b)   // schreibt NIEDRIGSTES Byte von b
    public void write(byte b[]) 
    ...
}
public abstract class InputStream implements Closeable {

    public abstract int read()  // liest EIN Byte, returnt [0, 255]
    public int read(byte b[])   // returnt Anzahl an gelesenen Byte
    public byte[] readNBytes(int len)
    public byte[] readAllBytes()
    ...
}
  • Implementiertung für diverse IO-Devices
  • 👎 mühsam 👎

DataOutput

public interface DataOutput {

    void writeBoolean(boolean v) throws IOException;
    void writeByte(int v) throws IOException;
    void writeShort(int v) throws IOException;
    void writeChar(int v) throws IOException;
    void writeInt(int v) throws IOException;
    void writeLong(long v) throws IOException;
    void writeFloat(float v) throws IOException;
    void writeDouble(double v) throws IOException;
    void writeBytes(String s) throws IOException;   // ⚠️ nur ASCII ⚠️
    void writeChars(String s) throws IOException;   // wieviele bytes?
    void writeUTF(String s) throws IOException;     // 2B length, data
}

DataInput

public interface DataInput {

    int skipBytes(int n) throws IOException;  // returnt wieviele geskippt
    boolean readBoolean() throws IOException;
    byte readByte() throws IOException;
    int readUnsignedByte() throws IOException;
    short readShort() throws IOException;
    int readUnsignedShort() throws IOException;
    char readChar() throws IOException;
    int readInt() throws IOException;
    long readLong() throws IOException;
    float readFloat() throws IOException;
    double readDouble() throws IOException;
    String readLine() throws IOException;   // ⚠️ nur ASCII ⚠️
    String readUTF() throws IOException;
}

werfen EOFException bei unerwartetem Dateiende


RandomAccessFile

public class RandomAccessFile 
        implements DataOutput, DataInput, Closeable {

    public RandomAccessFile(String name, String mode)
    public native long length()
    public native long getFilePointer()
    public void seek(long pos)
    public native void setLength(long newLength)
}
  • implementiert DataInput und DataOutput
  • sehr mächtig
void seek(long pos)
Filepointer wird auf Position pos gesetzt
void setLength(long newLength)
schneidet die Datei einfach ab


try (RandomAccessFile file = new RandomAccessFile("test.dat", "rw")) {
    file.write(-1);      // 1 Byte
    file.writeInt(42);    // 4 Byte
    file.writeUTF("Godzilla");
    file.writeUTF("ゴジラ");
    file.seek(5);
    String s = file.readUTF();
}
FF 00 00 00 2A 00 08 47 6F 64 7A 69 6C 6C 61 00
09 E3 82 B4 E3 82 B8 E3 83 A9

DataOutputStream/DataInputStream

public class FilterOutputStream extends OutputStream {

    protected OutputStream out;
    ...
}
public class DataOutputStream extends FilterOutputStream 
        implements DataOutput {

    public DataOutputStream(OutputStream out) {
        super(out);
    }

    ...
}
new DataInputStream(
        new BufferedInputStream(
                new FileInputStream(FILENAME)));

Decorator Pattern



byte[] data;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
     DataOutputStream output = new DataOutputStream(baos)) {
    output.writeInt(42);
    output.write(256);
    output.writeUTF("string");
    data = baos.toByteArray();
}
try (DataInputStream input = new DataInputStream(
        new ByteArrayInputStream(data))) {
    int i = input.readInt();
    int b = input.read();
    String string = input.readUTF();
}

Charstreams

public abstract class Writer implements Appendable, Closeable, Flushable {

    public void write(int c)    // schreibt einen char
    public void write(String str)
    public Writer append(char c)
    public Writer append(CharSequence csq)
    ...
}
public abstract class Reader implements Readable, Closeable {

    public int read()   // liest einen char
    public long skip(long n)
    public int read(char[] cbuf)
    ...
}
  • Implementiertung für diverse IO-Devices
  • 👎 mühsam 👎

PrintWriter/BufferedWriter

public class PrintWriter extends Writer {

    protected Writer out;

    public void print(...)
    public void println(...)
    ...
}
  • bekannt von System.out
  • unabhängig vom line ending
  • am besten um einen BufferedWriter wrappen, um die Performance zu erhöhen
new PrintWriter(new BufferedWriter(new CharArrayWriter()))

BufferedReader

public class BufferedReader extends Reader {

    private Reader in;

    public String readLine() // -> null bei EOF
    ...
}

zeilenweises Lesen unabhängig vom line ending


byte[] data;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
     PrintWriter writer = new PrintWriter(
             new BufferedWriter(new OutputStreamWriter(baos)))) {
    writer.println(42);
    writer.println("Hello World");
    writer.printf("%.3f", Math.PI);
    writer.flush();     // stream wird beim closen geflushed
    data = baos.toByteArray();
}
try (BufferedReader reader = new BufferedReader(
        new InputStreamReader(new ByteArrayInputStream(data)))) {
    String line;
    while ((line = reader.readLine()) != null) {
        ...
    }
}

Best practice

  • try-with verwenden
  • buffern
  • available()
  • ready()
  • zur EOS-Bestimmung Exceptions catchen
  • beim Lesen/Schreiben von Dateien
    Files-Methoden verwenden