Reader / Writer
Klassenhierarchie: Reader
Analog zu den Streams gibt es für das Lesen und Schreiben von Zeichenketten spezielle Klassen: Reader und Writer.
Ausgehend von einer abstrakten Basisklasse Reader
gibt es für unterschiedlichen Speicherorte und Zwecke spezielle Subklassen. Diese sind:
StringReader
– aus Strings lesenCharacterArrayReader
– aus char-Arrays lesenBufferedReader
– gepuffertes LesenPipedReader
– Verbindung von ThreadsInputStreamReader
– Verknüpfung von Stream und ReaderFileReader
– aus Dateien lesenFilterReader
– FilterPushbackReader
– lesen und zurückstellen von Zeichen
Methoden von Reader
int read()
– liest ein Zeichenint read(char[] cbuf)
– liest Zeichen in daschar
-Arrayint read(char[] cbuf, int off, int len)
– liest maximallen
Zeichen in daschar
-Arraycbuf
beginnend bei Positionoff
long skip(long n)
– überspringtn
Zeichenboolean ready()
– gibt an, ob der nächsteread()
auf dem Reader blockiert oder nicht
void mark(int readlimit)
– markiert die aktuelle Position im Reader und vergisst sie erst nachreadlimit
Bytes die daraufhin gelesen wurdenvoid reset()
– springt zu der mitmark()
markierten Stelle im Reader zurückboolean markSupported()
– zeigt an, ob der Reader überhaupt das setzen einer Marke mitmark()
unterstütztvoid close()
– schließt den Reader
Die Methoden des Reader entsprechen weitgehend denen der Streams, nur mit dem Unterschied, dass die Methoden char
liefern und nehmen anstatt byte
.
Auch hier ist wieder die Besonderheit zu beachten, dass die read
-Methode den Rückgabetyp int
hat, damit sie über den int-Wert -1
das Ende der Daten signalisieren kann. Deshalb darf man den Wert erst nach dem Vergleich mit -1
auf char
casten.
Zeichen von einem Reader lesen
Reader fr = new FileReader("/tmp/test.txt");
int daten;
while ((daten = fr.read()) > -1) {
char c = (char) daten;
// jetzt kann man etwas sinnvolles mit den Zeichen machen,
// die aus der Datei gelesen wurden
}
fr.close();
Reader fr = new FileReader("/tmp/test.txt");
char b;
while ((b = (char) fr.read()) > -1) { // FEHLER!!
// jetzt kann man etwas sinnvolles mit den Zeichen machen,
// die aus der Datei gelesen wurden
}
fr.close();
Dieser Code funktioniert nicht. Die Methode read()
signalisiert das Ende der Daten durch einen Rückgabewert von -1
als int
. Wenn man das Ergebnis aber vorher auf char
castet, wird das Lesen niemals beendet, da char
ein vorzeichenloser Datentyp ist und daher das Ergebnis eines Casts auf char
immer >= 0 ist.
Blöcke von einem Reader lesen
Reader fr = new FileReader("/tmp/test.txt");
char[] daten = new char[1024];
int charactersRead;
while ((charactersRead = fr.read(daten)) > -1) {
// jetzt kann man etwas sinnvolles mit den Zeichen machen,
// die aus der Datei gelesen wurden
}
fr.close();
Beispiel: StringReader
String text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n" +
"Nulla laoreet, sem vel mollis imperdiet, sapien mauris\n" +
"sollicitudin arcu, sed viverra nulla dui at est.\n" +
"Nunc est erat, semper id sollicitudin ut, pretium ac eros.\n";
Reader sr = new StringReader(text);
int gelesen;
while ((gelesen = sr.read()) > -1) {
System.out.print((char) gelesen);
}
sr.close();
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nulla laoreet, sem vel mollis imperdiet, sapien mauris
sollicitudin arcu, sed viverra nulla dui at est.
Nunc est erat, semper id sollicitudin ut, pretium ac eros.
Anstatt die Daten aus einer echten Quelle lesen, kann man mithilfe des StringReaders einen String als Quelle nehmen. Dies ist besonders angenehm für Tests, bei denen man auf so einfach die Funktionsweise z. B. eines Filter-Readers testen kann ohne Dateien anlegen zu müssen.
BufferedReader
BufferedReader
BufferedReader(Reader in)
BufferedReader(Reader in, int bufferSize)
String readLine()
Zu beachten ist, dass der BufferedReader
die sehr nützliche readLine()
-Methode einführt, mit der man Textdateien zeilenweise lesen kann. Das Ende der Datei wird bei dieser Methode durch den Rückgabewert null
signalisiert.
Beispiel: BufferedReader
String dateiname = "/tmp/text.txt";
BufferedReader reader = new BufferedReader(
new FileReader(dateiname));
String zeile;
int nummer = 1;
while ((zeile = reader.readLine()) != null) {
System.out.printf("%03d %s%n", nummer, zeile);
nummer++;
}
reader.close();
001 Lorem ipsum dolor sit amet, consectetur adipiscing elit.
002 Nulla laoreet, sem vel mollis imperdiet, sapien mauris
003 sollicitudin arcu, sed viverra nulla dui at est.
004 Nunc est erat, semper id sollicitudin ut, pretium ac eros.
Beispiel: Eigener FilterReader
public class UpperCaseReader extends FilterReader {
public UpperCaseReader(Reader in) {
super(in);
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
int result = super.read(cbuf, off, len);
for (int i = off; i < off + result; i++) {
cbuf[i] = Character.toUpperCase(cbuf[i]);
}
return result;
}
}
String dateiname = "/tmp/text.txt";
BufferedReader reader = new BufferedReader(
new UpperCaseReader(
new FileReader(dateiname)));
String zeile;
while ((zeile = reader.readLine()) != null) {
System.out.println(zeile);
}
reader.close();
LOREM IPSUM DOLOR SIT AMET, CONSECTETUR ADIPISCING ELIT.
NULLA LAOREET, SEM VEL MOLLIS IMPERDIET, SAPIEN MAURIS
SOLLICITUDIN ARCU, SED VIVERRA NULLA DUI AT EST.
NUNC EST ERAT, SEMPER ID SOLLICITUDIN UT, PRETIUM AC EROS.
Klassenhierarchie: Writer
Analog zum OutputStream
gibt es für das Schreiben von Zeichendaten die Subklassen von Writer
. Diese sind:
StringWriter
– In Strings schreibenCharacterArrayWriter
– In char-Arrays schreibenBufferedWriter
– Gepuffertes SchreibenPipedWriter
– Verbindung von ThreadsOutputStreamWriter
– Verbindung von Stream und WriterFileWriter
– In Datei schreibenPrintWriter
– Formatierte Ausgabe von DatentypenFilterWriter
– Filter
Die Methoden von Writer
void write(int c)
– schreibt ein Zeichenvoid write(char[] cbuf)
– schreibt alle Zeichen aus dem char-Arrayvoid write(char[] cbuf, int off, int len)
– schreibtlen
Zeichen aus dem char-Arraycbuf
beginnend beioff
void write(String str)
– schreibt den Stringstr
void write(String str, int off, int len)
– schreibtlen
Zeichen aus dem Stringstr
, beginnend beioff
Writer append(char c)
– schreibt ein Zeichenvoid flush()
– leert interne Puffer und bringt die Daten auf die Plattevoid close()
– schließt den Writer (impliziert einenflush()
)
Zeichen in einen Writer schreiben
Writer fw = new FileWriter("/tmp/mytext");
fw.write('T');
fw.write('e');
fw.write('x');
fw.write('t');
fw.write('\n');
fw.close();
> cat /tmp/mytext
Text
Strings in einen Writer schreiben
Writer fw = new FileWriter("/tmp/mytext");
String daten = "Dies ist ein Text";
fw.write(daten);
fw.write(daten, 0, 5);
fw.write(daten, 0, 5);
fw.write(daten, 12, 5);
fw.write(daten, 12, 5);
fw.write("\n");
fw.close();
> cat /tmp/mytext
Dies ist ein TextDies Dies Text Text
BufferedWriter
BufferedWriter
BufferedWriter(Writer out)
BufferedWriter(Writer out, int bufferSize)
void newLine()
Beispiel: CharArrayWriter
CharArrayWriter cw = new CharArrayWriter();
PrintWriter pw = new PrintWriter(cw);
pw.printf("<html><head><title>%s</title></head>%n", "Toller Titel");
pw.printf("<body>%s</body></html>", "Ganz viel Body");
pw.close();
String webseite = cw.toString();
System.out.println(webseite);
<html><head><title>Toller Titel</title></head>
<body>Ganz viel Body</body></html>
InputStreamReader etc.
- Manche APIs liefern nur Streams, manchmal möchte man die Daten aber mit einem Reader/Writer verarbeiten
- Sockets
- Servlet API
InputStreamReader
undOutputStreamWriter
dienen dazu, Streams und Reader/Writer miteinander zu verbinden- Verwendung als Filter bzw. Decorator
Beispiel: Einfacher HTTP-Client
Socket socket = new Socket("www.web.de", 80);
OutputStream os = socket.getOutputStream();
InputStream is = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
Writer writer = new OutputStreamWriter(os);
writer.write("GET / HTTP/1.0\r\n\r\n");
writer.flush();
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
writer.close();
socket.close();
HTTP/1.1 200 OK
Date: Sun, 13 Sep 2010 08:47:59 GMT
Server: Apache/2
Last-Modified: Sun, 13 Sep 2010 08:45:25 GMT
ETag: "133970-18cc3-9202d340"
Accept-Ranges: bytes
Content-Length: 101571
Cache-Control: max-age=0
Expires: Sun, 13 Sep 2010 08:47:59 GMT
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de"
id="buster">
<head>
<title>WEB.DE - E-Mail - Suche - DSL - Modem - Shopping
...
Die Klasse PrintWriter
- Hat
print(...)
undprintln(...)
Methoden für alle primitiven Datentypen,char[]
,String
undObject
- Die print-Methoden werfen keine
IOExceptions
, Fehler müssen mitcheckError
abgeholt werden - Bietet mit
printf(...)
eine mächtige Methode zur formatierten Ausgabe von Daten