Dateien/Streams - inf-swe

Werbung
Dateien/Streams
Arthur Zaczek
Okt 2015
Dateien/Streams
1
Input/Output
1.1
Was ist ein Stream?
Figure 1: InputStream
Figure 2: OutputStream
Graphik: (C) Copyright 1995-2009 Sun Microsystems, Inc.
1.2
Warum streamen?
• Reduktion des Speicherverbrauchs: es muss nicht der gesamte Input auf einmal im RAM
sein
• Überlappung von Übertragung und Verarbeitung:
– “pipelined requests” bei HTTP
– inkrementelle Verarbeitung von XML(“SAX”)
1.3
Primitiv: Byte-Streams
• Notwendig für Kommunikation mit Außenwelt:
– Dateien
– Netzwerk
C#
1
Dateien/Streams
• System.IO.Stream.FileStream
• System.Net.Sockets.NetworkStream
Java
• System.IO.Stream.FileStream
• java.net.Socket
– .getInputStream()
– .getOutputStream()
1.4
Byte-Stream in C
public class Stream
{
int ReadByte();
void WriteByte(byte value);
int Read(byte[] buffer,int offset, int count);
void Write(byte[] buffer,int offset, int count)
long Seek(long offset,SeekOrigin origin);
bool CanRead, CanWrite, CanSeek;
}
1.5
Byte-Streams in Java
public class java.io.InputStream {
int read();
int read(byte[] buffer);
int read(byte[] buffer,int offset, int length);
long skip(long count);
boolean markSupported();
void mark(int readLimit);
void reset();
}
public class java.io.OutputStream {
void write(int b);
void write(byte[] data);
void write(byte[] data,int offset, int length);
}
1.6
Datei öffnen für Lesen: C
using (FileStream fs = File.OpenRead(path))
{
// byte Buffer, Ziel für eingelesene Daten
byte[] b = new byte[1024];
while (fs.Read(b, 0, b.Length) > 0)
{
// dekodiert 1024 Bytes in 256 Zeichen; das funktioniert
// natürlich nur für Encodings mit konstanter Breite
Console.WriteLine(Encoding.UTF32.GetString(b));
2
Dateien/Streams
}
}
// fs wird automatisch von "using" geschlossen
1.7
Datei öffnen für Schreiben: Java
try (FileOutputStream fs = new FileOutputStream(path)) {
fs.write(data); // Bytearray mit kodierten Daten
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// fs.close() wird automatisch von "try ()" aufgerufen
1.8
Text I/O
• Text besteht nicht aus Bytes sondern aus Chars (zB UTF-8)
• daher: I/O in Bytes nur Mittel zum Zweck
• Kodierung und Dekodierung über Wrapperstreams:
– C#: TextReader/-Writer
– Java: Reader/Writer
1.9
TextReader und -Writer in CS
public class TextReader {
char Read();
int Read(char[] buffer,int offset, int count);
string ReadLine();
}
public class TextWriter {
void Write( bool/char/char[]/decimal/double/int/Int64/object/float/string/uint/UInt64);
void WriteLine(--"--);
}
1.10
Implementierungen in CS
• StringReader/Writer:
string test = "Fix, Schwyz! quäkt Jürgen vom Paß";
TextReader reader = new StringReader(test);
reader.ReadLine() == test;
TextWriter writer = new StringWriter();
writer.WriteLine(test);
writer.ToString() == test;
• Dateien:
TextReader reader = new StreamReader(File.OpenRead (path));
TextWriter writer = new StreamWriter(File.Open(path));
3
Dateien/Streams
1.11
(Text) Reader und Writer in Java
public class java.io.Reader {
int read();
int read(char[] buffer);
int read(char[] buffer,int offset, int length);
long skip(long count);
boolean markSupported();
void mark(int readLimit);
void reset();
}
public class java.io.Writer {
void write(int c);
void write(char[] data);
void write(char[] data, int offset, int length);
void write(String data);
void write(String data, int offset, int length);
}
1.12
Implementierungen in Java
• StringReader/Writer
Reader reader = new StringReader(sourceString);
Writer writer = new StringWriter();
String result = writer.toString()
• FileReader/Writer
Reader reader = new FileReader(path);
Writer writer = new FileWriter(path);
1.13
Binärdaten lesen/schreiben
• Effizient: interne Repräsentierung (Bitmuster) kann direkt gelesen/geschrieben werden.
Keine Konversion notwendig
• unportabel: interne Repräsentierung eben “intern”
• unsicher: Stream enthält keine Typinformation, keine Checksummen, keine Begin/Endemarker, beim Lesen muss man wissen was man erwartet
• intransparent: Binäre Repräsentation nicht durch einfaches Anschauen lesbar
1.14
BinaryReader/-Writer in CS
public class BinaryReader {
bool ReadBoolean();
byte ReadByte();
short/int/long ReadInt16/32/64();
float/double ReadSingle/Double();
string ReadString();
// ...
4
Dateien/Streams
}
public class BinaryWriter {
void Write(
bool/byte/short/int/long/float/
double/string/...);
}
1.15
Implementierung in CS
using(var writer = new BinaryReader(File.Open(path)))
{
writer.WriteBoolean(true);
writer.WriteDouble(2000.3);
writer.WriteString("Schwyz!");
}
using(var reader = new BinaryReader(File.OpenRead (path)))
{
bool someBool = reader.ReadBoolean();
float someFloat = reader.ReadFloat(); // schwerer Fehler!
string someString = reader.ReadString();
}
1.16
DataInput/-Output in Java
public class DataInput {
boolean readBoolean();
byte readByte();
short/int/long readShort/Int/Long();
float/double readFloat/Double();
String readUTF();
// ...
}
public class DataOutput {
void WriteBoolean/Byte/Short/Int/Long/
Float/Double/UTF(
boolean/int/short/int/long/float/
double/string/...);
}
1.17
Implementierung in Java
try (DataOutputStream writer = new DataOutputStream(new FileOutputStream(path))) {
writer.writeBoolean(true);
writer.writeDouble(2000.3);
writer.writeString("Schwyz!");
}
1.18
Puffern in Strömen
• Normalerweise verursacht jeder read()/write() einen Aufruf auf dem zugrundeliegenden
Speichermedium
5
Dateien/Streams
• je kleiner die Anfragen (zB zeichenweise mit ReadChar()) desto ineffizienter
• Die Buffered* Varianten hingegen lesen immer von einem Stream und immer in “großen”
Stücken (zB Java standardmäßig 8kB)
wesentlich höherer Durchsatz, dafür auch mehr Speicherverbrauch
1.19
Dateinamenverwaltung: CS
• DriveInfo.GetDrives(): Liste aller Laufwerke
• Path.Combine(driveinfo.Name, "foo", "blah"): “D:\foo\blah” auf Windows Desktop,
möglicherweise “/home/foo/blah” auf mono/Linux
• Path.GetFullPath("blah"): absoluter Pfad
1.20
•
•
•
•
1.21
Dateinamenverwaltung: Java
File.listRoots(): Liste aller Laufwerke
new File(file, "blah"): “D:\blah” auf Windows, möglicherweise “/. . . /blah” auf Linux
file.getAbsolutePath(): absoluter Pfad
file.getCanonicalPath(): “Standardversion” eines Pfades (ohne Symlinks, “.” und “..”)
Kurze Demo
Java, C#
6
Herunterladen