0% found this document useful (0 votes)
2 views20 pages

JavaStreams 11 Chap1

The document provides an overview of the Java Streams model, detailing the architecture for input and output streaming in Java. It explains the concepts of input and output streams, the delegation model, and the advantages of chaining streams to combine functionalities. Additionally, it outlines the structure of the InputStream and OutputStream classes, along with examples of their usage and the implementation of a filtering stream class for converting English to Pig Latin.

Uploaded by

balaji.pvb
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views20 pages

JavaStreams 11 Chap1

The document provides an overview of the Java Streams model, detailing the architecture for input and output streaming in Java. It explains the concepts of input and output streams, the delegation model, and the advantages of chaining streams to combine functionalities. Additionally, it outlines the structure of the InputStream and OutputStream classes, along with examples of their usage and the implementation of a filtering stream class for converting English to Pig Latin.

Uploaded by

balaji.pvb
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Java Streams

Chapter 1

The Java Streams Model

Rev. 1.1 [Link] 1-1


Copyright © 1999 William W. Provost
Java Streams

The Java Streams Model

Objectives

After completing this unit you will be able to:


• Describe the Java architecture’s model for streaming.
• Identify Java streaming classes for input and output
as delegating or non-delegating, and understand the
uses of each.
• Use the System fields to model the standard streams
such as input from and output to a console.
• Implement a delegating stream to perform filtering
on output or input, regardless of source and
destination media.

Rev. 1.1 [Link] 1-2


Copyright © 1999 William W. Provost
Java Streams

What is a Stream?

• Many languages and platforms define the general


concept of a stream: a queue of bytes which is being
simultaneously fed and consumed.
− The feeder or producer that puts bytes on the stream may be
a media-based entity such as a file, or a piece of code which
algorithmically decides what to write onto the stream when.
− The consumer of the stream likewise may be a target file,
network endpoint, or code which reads off of the stream.
− It is the broad heterogeneity of these roles that makes the
concept of a stream so powerful.
− It is also possible for the producer or consumer role to be
played by another stream, resulting in a chaining pattern.

• For purposes of understanding streams


programmatically, we categorize them by the role the
code that is using the stream might play:
− If the code is consuming bytes off of the stream, from
whatever source, the code treats it as an input stream.
− If the code is producing bytes for the stream, it is considered
to be an output stream.
− It is possible for some sort of running program to be on each
end of the stream, generally known as piping.
− Otherwise there is usually some durable medium involved
somewhere, for instance when reading or writing a disk file.

Rev. 1.1 [Link] 1-3


Copyright © 1999 William W. Provost
Java Streams

Java Streams

• In Java, streams are treated as input or output


streams, usually via an instance or subclass of one of
the classes in the [Link] package.
• There are no classes in this package which model
both input and output behaviors; contrast this to the
standard C++ ios class library.
• Generic stream behavior is modeled in base classes,
one each for input and output.
• Some subclasses of these model specific types of
stream endpoints, such as disk files or network ports.
• Many of the stream classes, however, have as their
responsibility some modification of input or output
behavior, and can only exist based on another input
or output stream instance, known as the delegate.
− There are a base class and several subclasses just for the
purpose of filtering either input or output in some way.
− Similarly, the Serialization API is based on stream classes
which delegate to any input/output stream instance.
− There are entire hierarchies of classes to model character-
based stream input and output, called Readers and Writers.

Rev. 1.1 [Link] 1-4


Copyright © 1999 William W. Provost
Java Streams

Advantages of Delegation

• Java’s delegation-based model allows each of many


possible stream behaviors to be encapsulated in a
different class.
− Instances of those classes can then be chained together, each
delegating to the next, up to a terminal or non-delegating
stream, to combine the desired behaviors.
− Each stream in the chain contributes some desired feature, be
it data formatting, buffering, or filtering out some unwanted
subset of possible bytes.

• There are many possible means of supporting a


diverse set of behaviors, including basing the
development of new behaviors in an inheritance
hierarchy.
• Delegation offers a much more flexible infrastructure
in this case.
− It is easy to choose exactly the features that will be needed
from a particular stream (or chain of streams), because each
stream object can be connected to any other.
− In an inheritance-based model, combining three features
would require the inheritance of three different classes,
unless one or more of those features could reasonably be
conceived as a specialization of another.
− In Java, of course, only single inheritance is possible, so a
delegation-based model seemed the obvious choice.

Rev. 1.1 [Link] 1-5


Copyright © 1999 William W. Provost
Java Streams

InputStream and OutputStream

• The basis of the [Link] package rests in two classes,


one each for input and output behaviors.
− InputStream defines basic behaviors for reading from a
stream.
− OutputStream defines a similarly basic interface for writing
to a stream.
− All other stream classes extend one of these two classes,
directly or through an intermediate class.

• Note that there is no combination of the two


interfaces
− No one class models both input and output behaviors.
− It is possible, however, to open two different streams, one for
input and one for output, on the same underlying target, such
as a disk file.

Rev. 1.1 [Link] 1-6


Copyright © 1999 William W. Provost
Java Streams

InputStream

• Here is the public interface of the abstract


InputStream class:
public abstract class InputStream
{
public abstract int read() throws IOException;
public int read(byte b[]) throws IOException;
public int read(byte b[], int off, int len)
throws IOException;
public long skip(long n) throws IOException;
public int available() throws IOException;
public void close() throws IOException;
public synchronized void mark(int readlimit);
public synchronized void reset()
throws IOException;
public boolean markSupported();
}

• Note that the only abstract method is the first


overload of read.
− Everything else is either implemented in terms of read or is
implemented trivially as a default.
− Subclasses must define that read method as appropriate to
their underlying medium or filtering behavior.

Rev. 1.1 [Link] 1-7


Copyright © 1999 William W. Provost
Java Streams

Input Streams

• The various input stream classes extend InputStream


according to the following hierarchy:

• Note the FilterInputStream class, whose primary


responsibility is simply to define a delegation
relationship with some other input stream.

Rev. 1.1 [Link] 1-8


Copyright © 1999 William W. Provost
Java Streams

OutputStream

• Here is the public interface of the abstract


OutputStream class:
public abstract class OutputStream
{
public abstract void write(int b)
throws IOException;
public void write(byte b[]) throws IOException;
public void write(byte b[], int off, int len)
throws IOException;
public void flush() throws IOException;
public void close() throws IOException;
}

• As with InputStream, only one method is abstract, in


this case the simplest overload of write.
− The subclass must define an implentation for this method.
− The other write methods delegate to the abstract one.
− flush and close are implemented trivially and are likely to be
overridden in various subclasses as appropriate.

Rev. 1.1 [Link] 1-9


Copyright © 1999 William W. Provost
Java Streams

Output Streams

• The various output stream classes extend


OutputStream according to the following hierarchy:

• Note the FilterOutputStream class, whose primary


responsibility is simply to define a delegation
relationship with another output stream.

Rev. 1.1 [Link] 1-10


Copyright © 1999 William W. Provost
Java Streams

Non-Delegating Streams

• The input and output stream types which do not


delegate to other streams each are targeted to some
specific endpoint or type of behavior:
− File I/O is modeled through the File*Stream classes; this
will be the focus of our study in the next chapter.
− You can model a chunk of memory as a stream for input or
output using the ByteArray*Stream classes.
− If you want to define a conduit or pipe through which two
objects can move information, you can use the
Piped*Stream classes. (Note – these do not map to any
underlying pipes support in any given platform.)
− Network communication, for instance through a TCP/IP
socket, can be modeled by a variety of stream classes, some
of which are supported in the [Link] package, and which
are beyond the scope of this module.
− Many distributed computing infrastructures at some point
require the ability to marshal a parameter or return value
between endpoints as part of a remote method call; this is
typically accomplished using a marshaling stream. This is
also beyond the scope of this module.

Rev. 1.1 [Link] 1-11


Copyright © 1999 William W. Provost
Java Streams

Delegating Streams

• There are many possible motivations or


responsibilities for stream classes that delegate to
other streams.
− The delegating stream can offer a higher-level interface to
reading or writing. For instance the Data*Stream classes
provide methods to read or write each of the Java primitive
types, plus some support for reading and writing strings.
− An even more abstract modeling of a stream is provided by
the PrintStream class (for output only), which writes only
strings to the stream, and thus automatically converts non-
strings to their string representations.
− Buffering behavior can be implemented in a delegating
stream, such that the delegator only contacts the delegate
when it has a full buffer of information, offering some
advantages in efficient use of an underlying medium. The
Buffered*Stream classes add exactly this capability.
− For parsers which would sometimes like to see a byte, make
some decision about what to do next, and possibly put the
byte back to be read again by another piece of code, the
PushbackInputStream (input only) offers a buffer of
configurable size which is cached and indexed.

• The power of the delegation-based model for streams


in Java can be seen in the fact that any of the above
delegating streams can be instantiated and chained to
any other type of output stream, including another
delegating stream.

Rev. 1.1 [Link] 1-12


Copyright © 1999 William W. Provost
Java Streams

Chaining Streams

• As an example of chaining delegating streams


together, consider the following code:
public static void main (String[] args)
{
try
{
FileOutputStream fos =
new FileOutputStream (“[Link]”);
BufferedOutputStream bos =
new BufferedOutputStream (fos);
DataOutputStream dos =
new DataOutputStream (bos);

[Link] (5);
[Link] (“Hello, UTF!”);
}
catch (IOException ex)
{
[Link] (“Bad things happened.”);
}
}

• This builds a buffering stream based on a data-


formatting stream which is based in turn on a file
output stream.
• The result is that each of the individual features
(buffering, automatic data formatting per type, and
file-targeted output) is offered by the combination.

Rev. 1.1 [Link] 1-13


Copyright © 1999 William W. Provost
Java Streams

Justifying Text

• As a simple example of a delegating stream, consider


the Justifier class, which can be found in
Examples\Justifier.
• This class extends FilterOutputStream, and so
automatically gets method implementations that
delegate to another OutputStream.
public class Justifier
extends [Link]
{
public Justifier (OutputStream delegate)
{
super (delegate);
}
...

• It adds methods to write strings both left- and right-


justified to a provided field length.
protected void justify (int length)
throws IOException
{
if (length <= 0) return;
while (length-- != 0)
[Link] (' ');
}

public void rightJustify


(String text, int fieldLength)
throws IOException
{
justify (fieldLength - [Link] ());
[Link] ([Link] ());
}

Rev. 1.1 [Link] 1-14


Copyright © 1999 William W. Provost
Java Streams

Readers and Writers

• There are hierarchies of classes known as Readers


and Writers in the [Link] package as well, which are
designed to manage character-based streams.

• Some of these delegate to raw stream objects, and


some manage their underlying media directly.

Rev. 1.1 [Link] 1-15


Copyright © 1999 William W. Provost
Java Streams

Standard Streams

• The [Link] class holds public fields which


model standard streams:
− [Link] represents the standard output stream, for
instance to print responses to a console.
− [Link] represents the standard input stream, typically
piped from the keyboard input of the interactive user.

• It is common practice to write diagnostic lines to


[Link] during development:
[Link] (“Success in all endeavors.”);
for (int i = 0; i < [Link]; ++i)
[Link] (charArray[i]);
[Link] ();

• These stream references are to objects which are


already initialized for you by the JRE, but which
otherwise are like any other Java objects.
− They can be passed from method to method as parameters.
− They can be used to initialize object fields.
− We will see an example of this in the demo in chapter 2.

Rev. 1.1 [Link] 1-16


Copyright © 1999 William W. Provost
Java Streams

Lab 1

Pretty Bad Privacy

In this lab you will implement a filtering stream class that converts
English into Pig Latin. Your class will extend OutputStream and
will chain to any PrintStream; as characters are written to your
stream you will cache them appropriately, and when you encounter
whitespace you will write the modified tokens out to the delegate
stream.

Suggested Time: 45 minutes

Rev. 1.1 [Link] 1-17


Copyright © 1999 William W. Provost
Java Streams

Summary

• The Core API defines a simple but powerful model


for stream programming.
• Many provided classes offer useful features that can
be chained to any type of stream implementation.
• Many extensions of this system are therefore possible,
each new extension implicitly leveraging a broad
featureset.
• Some of the classes in the [Link] package directly
encapsulate file I/O, and these will be treated in the
next chapter.
• Some extensions implemented elsewhere in the Core
API include network communication streams, which
are covered in another course, and I/O from
compressed archives, in the [Link] package.

Rev. 1.1 [Link] 1-18


Copyright © 1999 William W. Provost
Java Streams

Lab 1

Pretty Bad Privacy

Introduction

In this lab you will implement a filtering stream class that converts English into Pig
Latin. Your class will extend OutputStream and will chain to any PrintStream; as
characters are written to your stream you will cache them appropriately, and when you
encounter whitespace you will write the modified tokens out to the delegate stream.

Suggested Time: 45 minutes

Directories: Labs\JavaMod5Lab1 (do your work here)


Examples\PigLatin (answer)

Files: [Link]

Packages: [Link]

Instructions
1. Create a new class Translator. Import the [Link] package, and make your class
extend OutputStream.

2. Add a field delegate of type PrintStream, and initialize it in a constructor that takes
a PrintStream argument.

3. Add String fields beginning, middle, and ending. Initialize the first two to be empty
strings (not null) and make the last one static final an initialize to “ay “. (Note the
trailing space in the string.)

4. Add a boolean field foundMiddle, initializing it to false.

5. Add a static [Link] vowels. In a static initializer block initialize this to


a new [Link] and add a Character for each of the vowels, as in:
[Link] (new Character (‘a’));

6. Implement a dummy override of write (the overload that takes an int): just print the
character to the PrintStream. (Note that an output stream and a print stream have
different ways of treating non-printable bytes, so this is not the most robust filtering
stream in creation, but hey – for Pig Latin, it’ll do.)

Rev. 1.1 [Link] 1-19


Copyright © 1999 William W. Provost
Java Streams

7. Implement an application method main. In a try-catch system to deal with


IOExceptions, create an instance of Translator, passing [Link] as the delegate
stream. Run an infinite loop that reads a byte from [Link] and echoes it by calling
write on the translator instance. Build and test at this point. You should see that
when you type a line of text it is echoed to you. (Each character is not echoed
immediately because the standard input stream implementation automatically echoes
by itself, and only unlocks the output stream line-by-line.) There is no breakout
condition for the loop so to stop you will have to Control-C it.

8. Now we’re ready to try translating. Empty out your write implementation and start
again. First get the output as a char by doing a conversion on the method argument.
Call the local variable character.

9. Compare character to the character literal for a space. (Remember to use single
quotes, otherwise your literal will be taken by the compiler as a String.) If they
compare, you are ready to write a new token to the delegate. Just write an empty
code block for the moment; we’ll look at how the incoming characters are parsed
before we consider how to write the modified token.

10. If they don’t compare (else and a second code block), you have a letter character.
The job here is to find the first character of the new word, which is the first vowel
encountered; then you will chop off the beginning consonants, put them at the end,
and append the ending string. So first, if foundMiddle is still false, see if the vowels
collection contains the character – for this you must build a new Character object on
the fly:
if (!foundMiddle && [Link] (new Character (character)))
foundMiddle = true;

11. Now – still in the else block – you can append the current character to either the
beginning or middle strings, according to the value of foundMiddle.

12. Go back to the empty block under if. When we encounter a space character, we know
the whole word, and we’ve accumulated its characters into two segments. We will
rearrange the order of those segments and add a third, which is the ending string. So
call [Link] for each segment: middle, beginning, ending.

13. In the same block, re-initialize beginning, middle, and foundMiddle to their original
values in order to be ready to parse the next word. Build and test at this point – see
sample output below.
java [Link]
this is a test of the emergency broadcast system
isthay isay aay esttay ofay ethay emergencyay oadcastbray emsystay

Rev. 1.1 [Link] 1-20


Copyright © 1999 William W. Provost

You might also like