Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.
 
Inhaltsverzeichnis
Vorwort
1 Neues in Java 8 und Java 7
2 Fortgeschrittene String-Verarbeitung
3 Threads und nebenläufige Programmierung
4 Datenstrukturen und Algorithmen
5 Raum und Zeit
6 Dateien, Verzeichnisse und Dateizugriffe
7 Datenströme
8 Die eXtensible Markup Language (XML)
9 Dateiformate
10 Grafische Oberflächen mit Swing
11 Grafikprogrammierung
12 JavaFX
13 Netzwerkprogrammierung
14 Verteilte Programmierung mit RMI
15 RESTful und SOAP-Web-Services
16 Technologien für die Infrastruktur
17 Typen, Reflection und Annotationen
18 Dynamische Übersetzung und Skriptsprachen
19 Logging und Monitoring
20 Sicherheitskonzepte
21 Datenbankmanagement mit JDBC
22 Java Native Interface (JNI)
23 Dienstprogramme für die Java-Umgebung
Stichwortverzeichnis

Jetzt Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Java SE 8 Standard-Bibliothek von Christian Ullenboom
Das Handbuch für Java-Entwickler
Buch: Java SE 8 Standard-Bibliothek

Java SE 8 Standard-Bibliothek
Pfeil 7 Datenströme
Pfeil 7.1 Stream-Klassen für Bytes und Zeichen
Pfeil 7.1.1 Lesen aus Dateien und Schreiben in Dateien
Pfeil 7.1.2 Byteorientierte Datenströme über Files beziehen
Pfeil 7.1.3 Zeichenorientierte Datenströme über Files beziehen
Pfeil 7.1.4 Funktion von OpenOption bei den Files.newXXX(…)-Methoden
Pfeil 7.1.5 Ressourcen aus dem Klassenpfad und aus JAR‐Archiven laden
Pfeil 7.1.6 Die Schnittstellen Closeable, AutoCloseable und Flushable
Pfeil 7.2 Basisklassen für die Ein-/Ausgabe
Pfeil 7.2.1 Die abstrakten Basisklassen
Pfeil 7.2.2 Übersicht über Ein-/Ausgabeklassen
Pfeil 7.2.3 Die abstrakte Basisklasse OutputStream
Pfeil 7.2.4 Ein Datenschlucker *
Pfeil 7.2.5 Die abstrakte Basisklasse InputStream
Pfeil 7.2.6 Ströme mit SequenceInputStream zusammensetzen *
Pfeil 7.2.7 Die abstrakte Basisklasse Writer
Pfeil 7.2.8 Die Schnittstelle Appendable *
Pfeil 7.2.9 Die abstrakte Basisklasse Reader
Pfeil 7.3 Formatierte Textausgaben
Pfeil 7.3.1 Die Klassen PrintWriter und PrintStream
Pfeil 7.3.2 System.out, System.err und System.in
Pfeil 7.4 Die FileXXX-Stromklassen
Pfeil 7.4.1 Kopieren mit FileOutputStream und FileInputStream
Pfeil 7.4.2 Das FileDescriptor-Objekt *
Pfeil 7.4.3 Mit dem FileWriter Texte in Dateien schreiben
Pfeil 7.4.4 Zeichen mit der Klasse FileReader lesen
Pfeil 7.5 Schreiben und Lesen aus Strings und Byte-Feldern
Pfeil 7.5.1 Mit dem StringWriter ein String-Objekt füllen
Pfeil 7.5.2 CharArrayWriter
Pfeil 7.5.3 StringReader und CharArrayReader
Pfeil 7.5.4 Mit ByteArrayOutputStream in ein Byte-Feld schreiben
Pfeil 7.5.5 Mit ByteArrayInputStream aus einem Byte-Feld lesen
Pfeil 7.6 Datenströme filtern und verketten
Pfeil 7.6.1 Streams als Filter verketten (verschachteln)
Pfeil 7.6.2 Gepufferte Ausgaben mit BufferedWriter und BufferedOutputStream
Pfeil 7.6.3 Gepufferte Eingaben mit BufferedReader/BufferedInputStream
Pfeil 7.6.4 LineNumberReader zählt automatisch Zeilen mit *
Pfeil 7.6.5 Daten mit der Klasse PushbackReader zurücklegen *
Pfeil 7.6.6 DataOutputStream/DataInputStream *
Pfeil 7.6.7 Basisklassen für Filter *
Pfeil 7.6.8 Die Basisklasse FilterWriter *
Pfeil 7.6.9 Ein LowerCaseWriter *
Pfeil 7.6.10 Eingaben mit der Klasse FilterReader filtern *
Pfeil 7.6.11 Anwendungen für FilterReader und FilterWriter *
Pfeil 7.7 Vermittler zwischen Byte-Streams und Unicode-Strömen
Pfeil 7.7.1 Datenkonvertierung durch den OutputStreamWriter
Pfeil 7.7.2 Automatische Konvertierungen mit dem InputStreamReader
Pfeil 7.8 Kommunikation zwischen Threads mit Pipes *
Pfeil 7.8.1 PipedOutputStream und PipedInputStream
Pfeil 7.8.2 PipedWriter und PipedReader
Pfeil 7.9 Prüfsummen
Pfeil 7.9.1 Die Schnittstelle Checksum
Pfeil 7.9.2 Die Klasse CRC32
Pfeil 7.9.3 Die Adler32-Klasse
Pfeil 7.10 Persistente Objekte und Serialisierung
Pfeil 7.10.1 Objekte mit der Standardserialisierung speichern und lesen
Pfeil 7.10.2 Zwei einfache Anwendungen der Serialisierung *
Pfeil 7.10.3 Die Schnittstelle Serializable
Pfeil 7.10.4 Nicht serialisierbare Attribute aussparen
Pfeil 7.10.5 Das Abspeichern selbst in die Hand nehmen
Pfeil 7.10.6 Tiefe Objektkopien *
Pfeil 7.10.7 Versionenverwaltung und die SUID
Pfeil 7.10.8 Wie die ArrayList serialisiert *
Pfeil 7.10.9 Probleme mit der Serialisierung
Pfeil 7.11 Alternative Datenaustauschformate
Pfeil 7.11.1 Serialisieren in XML-Dateien
Pfeil 7.11.2 XML-Serialisierung von JavaBeans mit JavaBeans Persistence *
Pfeil 7.11.3 Die Open-Source-Bibliothek XStream *
Pfeil 7.11.4 Binäre Serialisierung mit Google Protocol Buffers *
Pfeil 7.12 Zum Weiterlesen
 
Zum Seitenanfang

7.8Kommunikation zwischen Threads mit Pipes * Zur vorigen ÜberschriftZur nächsten Überschrift

Die Kommunikation zwischen Programmteilen kann auf vielfältige Weise geschehen. Einige Möglichkeiten haben wir bei Threads kennengelernt. Bei getrennten Programmen lässt sich die Kommunikation über Dateien realisieren. Auch Datenströme können von einem Teil geschrieben und vom anderen gelesen werden. Wenn wir jedoch mit Threads arbeiten, wäre eine Kommunikation über Dateien zwar denkbar, aber zu aufwändig. Ein anderes Stromkonzept ist praktisch.

 
Zum Seitenanfang

7.8.1PipedOutputStream und PipedInputStream Zur vorigen ÜberschriftZur nächsten Überschrift

Einfacher ist der Austausch der Daten über eine so genannte Pipe. Sie wird über Paare spezieller Stromklassen gebildet:

  • PipedOutputStream, PipedInputStream bzw.

  • PipedWriter, PipedReader

Die PipedXXX-Klassen sind übliche Unterklassen von OutputStream/InputStream und Writer/Reader (im nächsten Beispiel verfolgen wir die Byte-Variante). Wenn dann Threads Daten austauschen wollen, kann ein Produzent sie über write(…) in den Ausgabestrom schreiben, und der andere Thread wird sie dort über read(…) empfangen können.

Natürlich muss ein schreibender Pipe-Strom wissen, wer der Empfänger ist. Daher müssen die Schreib-/Lese-Pipes miteinander verbunden werden. Eine Möglichkeit bietet connect().

[zB]Beispiel

Ein PipedOutputStream soll mit einem PipedInputStream verbunden werden:

PipedOutputStream pos = new PipedOutputStream();
PipedInputStream pis = new PipedInputStream();
pos.connect( pis );
// oder pis.connect( pos );

Werden jetzt Daten produziert und in den pos geschrieben, kommen sie über den pis wieder an und können dort konsumiert werden.

Ob wir nun vom PipedOutputStream die Methode connect(PipedInputStream) nehmen oder vom PipedInputStream die Methode connect(PipedOutputStream), ist dabei egal.

Anstatt nach dem Aufbau der Ströme über den Standard-Konstruktor beide mit connect(…) zu verbinden, gibt es eine alternative Lösung: Entweder lässt sich nach dem Erzeugen des PipedOutputStream über den Standard-Konstruktor das frische Stromobjekt in den parametrisierten Konstruktor von PipedInputStream übergeben oder eben umgekehrt ein neues PipedInputStream-Objekt in den parametrisierten Konstruktor von PipedOutputStream legen.

UML-Diagramm mit den Beziehungen zwischen den PipedXXX-Klassen

Abbildung 7.13UML-Diagramm mit den Beziehungen zwischen den PipedXXX-Klassen

[zB]Beispiel

Verbinde den Eingabe-Stream pis mit dem Ausgabe-Stream pos:

PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream( pis );

Interna

Der Austausch der Daten geschieht über einen internen Puffer, den PipedInputStream anlegt. Die Daten, die PipedOutputStream über write(…) schreiben soll, gelangen direkt zum Puffer des Eingabestroms. Werfen wir einen kurzen Blick auf die relevanten Teile der Implementierung:

Listing 7.25java/lang/PipedOutputStream.java, Ausschnitt

class PipedOutputStream extends OutputStream {

private PipedInputStream sink;

public PipedOutputStream( PipedInputStream snk )
throws IOException {
/* Auskommentierte Fehlerbehandlung */
sink = snk;
snk.in = –1;
snk.out = 0;
snk.connected = true;
}

public void write( int b ) throws IOException {
if ( sink == null )
throw new IOException( "Pipe not connected" );

sink.receive( b );
}
}

Der PipedInputStream nutzt intern einen Puffer von standardmäßig 1.024 Elementen. Das bedeutet: Der Schreibende kann standardmäßig bis zu 1.024 Byte (oder Zeichen bei PipedReader) produzieren, bis die Kommunikation stoppen muss. Denn mit dieser Größe ist der Puffer voll und der Produzent blockiert; der Lesende muss den Puffer erst leeren, damit der Konsument weiterarbeiten darf. Umgekehrt bedeutet dies, dass der lesende Thread bei ungenügend vielen Zeichen warten muss, bis der Schreiber die nötige Anzahl hinterlegt hat. Dafür wird intern mittels Thread-Synchronisation gearbeitet. Lebt die andere Seite nicht mehr, gibt es eine IOException.

Die Größe des Puffers lässt sich über einen Konstruktor wie PipedInputStream(int pipeSize), PipedInputStream(PipedOutputStream src, int pipeSize), PipedReader(int pipeSize) oder PipedReader(PipedWriter src, int pipeSize) setzen.

 
Zum Seitenanfang

7.8.2PipedWriter und PipedReader Zur vorigen ÜberschriftZur nächsten Überschrift

Die Klassen PipedWriter und PipedReader sind die char-Varianten für die sonst byteorientierten Klassen PipedOutputStream und PipedInputStream. Diese sollen uns als Beispiel dienen. Zwei Threads arbeiten miteinander und tauschen Daten aus. Der eine Thread produziert Zufallszahlen, die ein anderer Thread auf dem Bildschirm darstellt:

Listing 7.26com/tutego/insel/io/stream/PipeDemo.java, PipeRandomWriter

package com.tutego.insel.io.stream;

import java.io.*;

class PipeRandomWriter extends PipedWriter implements Runnable {
@Override public void run() {
while ( true )
try {
write( String.format( "%f%n", Math.random() ) );
Thread.sleep( 200 );
}
catch ( Exception e ) { e.printStackTrace(); }
}
}

Die Klasse ist eine Spezialisierung von PipedWriter und produziert in run() endlos Zufallszahlen, die in den Ausgabestrom vom PipedWriter geschoben werden. Der PipeRandomReader wiederum ist ein PipedReader, der über einen BufferedReader alle geschriebenen Zeilen ausliest:

Listing 7.27com/tutego/insel/io/stream/PipeDemo.java, PipeRandomReader

class PipeRandomReader extends PipedReader implements Runnable {
@Override public void run() {
BufferedReader br = new BufferedReader( this );
while ( true )
try {
System.out.println( br.readLine() );
}
catch ( IOException e ) { e.printStackTrace(); }
}
}

Das Hauptprogramm erzeugt die beiden spezialisierten Pipes und verbindet sie. Danach werden die Threads gestartet:

Listing 7.28com/tutego/insel/io/stream/PipeDemo.java, PipeDemo main()

PipeRandomWriter out = new PipeRandomWriter();
PipeRandomReader in = new PipeRandomReader();
in.connect( out );

new Thread( out ).start();
new Thread( in ).start();

 


Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

<< zurück
Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Java SE 8 Standard-Bibliothek Java SE 8 Standard-Bibliothek
Jetzt Buch bestellen

 Buchempfehlungen
Zum Rheinwerk-Shop: Java ist auch eine Insel
Java ist auch eine Insel


Zum Rheinwerk-Shop: Professionell entwickeln mit Java EE 8
Professionell entwickeln mit Java EE 8


Zum Rheinwerk-Shop: Besser coden
Besser coden


Zum Rheinwerk-Shop: Entwurfsmuster
Entwurfsmuster


Zum Rheinwerk-Shop: IT-Projektmanagement
IT-Projektmanagement


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo

 
 


Copyright © Rheinwerk Verlag GmbH 2018
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

 
Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern