epubjs
Version:
Render ePub documents in the browser, across many devices
345 lines (344 loc) • 73.3 kB
HTML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Streams</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body><div class="sect1" title="Streams"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-12-SECT-1"/>Streams</h1></div></div></div><p>Most fundamental I/O in Java is based on
<span class="emphasis"><em>streams</em></span>. A stream represents a flow of data with (at
least conceptually) a <span class="emphasis"><em>writer</em></span> at one end and a
<span class="emphasis"><em>reader</em></span> at the other. When you are working with the
<code class="literal">java.io</code> package to perform terminal
input and output, reading or writing files, or communicating through
sockets in Java, you are using various types of streams. Later in this
chapter, we’ll look at the NIO package, which introduces a similar concept
called a <span class="emphasis"><em>channel</em></span>. One difference betwen the two is
that streams are oriented around bytes or characters while channels are
oriented around “buffers” containing those data types—yet they perform
roughly the same job. Let’s start by summarizing the available types of
streams:</p><div class="variablelist"><dl><dt><span class="term"><code class="literal">InputStream</code>, <code class="literal">OutputStream</code></span></dt><dd><p>Abstract classes that define the basic functionality for
reading or writing an unstructured sequence of bytes. All other byte
streams in Java are built on top of the basic <code class="literal">InputStream</code> and <code class="literal">OutputStream</code>.</p></dd><dt><span class="term"><code class="literal">Reader</code>, <code class="literal">Writer</code></span></dt><dd><p>Abstract classes that define the basic functionality for
reading or writing a sequence of character data, with support for
Unicode. All other character streams in Java are built on top of
<code class="literal">Reader</code> and <code class="literal">Writer</code>.</p></dd><dt><span class="term"><code class="literal">InputStreamReader</code>, <code class="literal">OutputStreamWriter</code></span></dt><dd><p>Classes that bridge byte and character streams by converting
according to a specific character encoding scheme. (Remember: in
Unicode, a character is not a byte!)</p></dd><dt><span class="term"><code class="literal">DataInputStream</code>, <code class="literal">DataOutputStream</code></span></dt><dd><p>Specialized stream filters that add the ability to read and
write multibyte data types, such as numeric primitives and <code class="literal">String</code> objects in a universal
format.</p></dd><dt><span class="term"><code class="literal">ObjectInputStream</code>, <code class="literal">ObjectOutputStream</code></span></dt><dd><p>Specialized stream filters that are capable of writing whole
groups of serialized Java objects and reconstructing them.</p></dd><dt><span class="term"><code class="literal">BufferedInputStream</code>, <code class="literal">BufferedOutputStream</code>, <code class="literal">BufferedReader</code>, <code class="literal">BufferedWriter</code></span></dt><dd><p>Specialized stream filters that add buffering for additional
efficiency. For real-world I/O, a buffer is almost always
used.</p></dd><dt><span class="term"><code class="literal">PrintStream</code>, <code class="literal">PrintWriter</code></span></dt><dd><p>Specialized streams that simplify printing text.</p></dd><dt><span class="term"><code class="literal">PipedInputStream</code>, <code class="literal">PipedOutputStream</code>,
<code class="literal">PipedReader</code>, <code class="literal">PipedWriter</code></span></dt><dd><p>“Loopback” streams that can be used in pairs to move data
within an application. Data written into a <code class="literal">PipedOutputStream</code> or <code class="literal">PipedWriter</code> is read from its corresponding
<code class="literal">PipedInputStream</code> or <code class="literal">PipedReader</code>.</p></dd><dt><span class="term"><code class="literal">FileInputStream</code>, <code class="literal">FileOutputStream</code>, <code class="literal">FileReader</code>, <code class="literal">FileWriter</code></span></dt><dd><p>Implementations of <code class="literal">InputStream</code>, <code class="literal">OutputStream</code>, <code class="literal">Reader</code>, and <code class="literal">Writer</code> that read from and write to files
on the local filesystem.</p></dd></dl></div><div class="figure"><a id="learnjava3-CHP-12-FIG-1"/><div class="figure-contents"><div class="mediaobject"><a id="I_12_tt759"/><img src="httpatomoreillycomsourceoreillyimages1707640.png" alt="author="pat” timestamp="20121117T215954-0600” comment="I think this originally came from the nutshell book. Do they have an update for this diagram that we could use? (Maybe one for NIO?)”The java.io package"/></div></div><p class="title">Figure 12-1. The java.io package</p></div><p>Streams in Java are one-way streets. The <code class="literal">java.io</code> input and output classes represent the
ends of a simple stream, as shown in <a class="xref" href="ch12s01.html#learnjava3-CHP-12-FIG-2" title="Figure 12-2. Basic input and output stream functionality">Figure 12-2</a>. For bidirectional conversations,
you’ll use one of each type of stream.</p><div class="figure"><a id="learnjava3-CHP-12-FIG-2"/><div class="figure-contents"><div class="mediaobject"><a id="I_12_tt760"/><img src="httpatomoreillycomsourceoreillyimages1707641.png" alt="Basic input and output stream functionality"/></div></div><p class="title">Figure 12-2. Basic input and output stream functionality</p></div><p><a id="I_indexterm12_id751101" class="indexterm"/> <code class="literal">InputStream</code> and
<a id="I_indexterm12_id751112" class="indexterm"/><code class="literal">OutputStream</code> are
<span class="emphasis"><em>abstract</em></span> classes that define the lowest-level
interface for all byte streams. They contain methods for reading or
writing an unstructured flow of byte-level data. Because these classes are
abstract, you can’t create a generic input or output stream. Java
implements subclasses of these for activities such as reading from and
writing to files and communicating with sockets. Because all byte streams
inherit the structure of <code class="literal">InputStream</code> or
<code class="literal">OutputStream</code>, the various kinds of byte
streams can be used interchangeably. A method specifying an <code class="literal">InputStream</code> as an argument can accept any
subclass of <code class="literal">InputStream</code>. Specialized
types of streams can also be layered or wrapped around basic streams to
add features such as buffering, filtering, or handling higher-level data
types.</p><p><a id="I_indexterm12_id751159" class="indexterm"/> <code class="literal">Reader</code> and <a id="I_indexterm12_id751170" class="indexterm"/><code class="literal">Writer</code> are very much like
<code class="literal">InputStream</code> and <code class="literal">OutputStream</code>, except that they deal with
characters instead of bytes. As true character streams, these classes
correctly handle Unicode characters, which is not always the case with
byte streams. Often, a bridge is needed between these character streams
and the byte streams of physical devices, such as disks and networks.
<code class="literal">InputStreamReader</code> and <code class="literal">OutputStreamWriter</code> are special classes that use
a <span class="emphasis"><em>character-encoding scheme</em></span> to translate between
character and byte streams.</p><p>This section describes all the interesting stream types with the
exception of <code class="literal">FileInputStream</code>, <code class="literal">FileOutputStream</code>, <code class="literal">FileReader</code>, and <code class="literal">FileWriter</code>. We postpone the discussion of file
streams until the next section, where we cover issues involved with
accessing the filesystem in Java.</p><div class="sect2" title="Basic I/O"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-12-SECT-1.1"/>Basic I/O</h2></div></div></div><p><a id="idx10721" class="indexterm"/> <a id="idx10750" class="indexterm"/>The prototypical example of an <a id="I_indexterm12_id751269" class="indexterm"/><code class="literal">InputStream</code> object is
the <span class="emphasis"><em>standard input</em></span> of a Java application. Like
<code class="literal">stdin</code> in C or <code class="literal">cin</code> in C++, this is the source of input to a
command-line (non-GUI) program. It is an input stream from the
environment—usually a terminal window or possibly the output of another
command. The <a id="I_indexterm12_id751298" class="indexterm"/><code class="literal">java.lang.System</code> class,
a general repository for system-related resources, provides a reference
to the standard input stream in the static variable <a id="I_indexterm12_id751310" class="indexterm"/><a id="I_indexterm12_id751315" class="indexterm"/><a id="I_indexterm12_id751321" class="indexterm"/><code class="literal">System.in</code>. It also
provides a <span class="emphasis"><em>standard output stream</em></span> and a
<span class="emphasis"><em>standard error stream</em></span> in the <a id="I_indexterm12_id751339" class="indexterm"/><code class="literal">out</code> and <a id="I_indexterm12_id751349" class="indexterm"/><code class="literal">err</code> variables,
respectively.<sup>[<a id="learnjava3-CHP-12-FN-1" href="#ftn.learnjava3-CHP-12-FN-1" class="footnote">34</a>]</sup> The following example shows the correspondence:</p><a id="I_12_tt761"/><pre class="programlisting"> <code class="n">InputStream</code> <code class="n">stdin</code> <code class="o">=</code> <code class="n">System</code><code class="o">.</code><code class="na">in</code><code class="o">;</code>
<code class="n">OutputStream</code> <code class="n">stdout</code> <code class="o">=</code> <code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">;</code>
<code class="n">OutputStream</code> <code class="n">stderr</code> <code class="o">=</code> <code class="n">System</code><code class="o">.</code><code class="na">err</code><code class="o">;</code></pre><p>This snippet hides the fact that <code class="literal">System.out</code> and <code class="literal">System.err</code> aren’t just <code class="literal">OutputStream</code> objects, but more specialized and
useful <code class="literal">PrintStream</code> objects. We’ll
explain these later, but for now we can reference <code class="literal">out</code> and <code class="literal">err</code>
as <code class="literal">OutputStream</code> objects because they
are derived from <code class="literal">OutputStream</code>.</p><p>We can read a single byte at a time from standard input with the
<code class="literal">InputStream</code>’s <a id="I_indexterm12_id751434" class="indexterm"/><code class="literal">read()</code> method. If you
look closely at the API, you’ll see that the <code class="literal">read()</code> method of the base <code class="literal">InputStream</code> class is an <code class="literal">abstract</code> method. What lies behind <code class="literal">System.in</code> is a particular implementation of
<code class="literal">InputStream</code> that provides the real
implementation of the <code class="literal">read()</code>
method:</p><a id="I_12_tt762"/><pre class="programlisting"> <code class="k">try</code> <code class="o">{</code>
<code class="kt">int</code> <code class="n">val</code> <code class="o">=</code> <code class="n">System</code><code class="o">.</code><code class="na">in</code><code class="o">.</code><code class="na">read</code><code class="o">();</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">IOException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code>
<code class="o">...</code>
<code class="o">}</code></pre><p>Although we said that the <code class="literal">read()</code> method reads a byte value, the return
type in the example is <code class="literal">int</code>, not
<code class="literal">byte</code>. That’s because the <code class="literal">read()</code> method of basic input streams in Java
uses a convention carried over from the C language to indicate the end
of a stream with a special value. Data byte values are returned as
unsigned integers in the range 0 to 255 and the special value of
<code class="literal">-1</code> is used to indicate that end of
stream has been reached. You’ll need to test for this condition when
using the simple <code class="literal">read()</code> method. You
can then cast the value to a byte if needed. The following example reads
each byte from an input stream and prints its value:</p><a id="I_12_tt763"/><pre class="programlisting"> <code class="k">try</code> <code class="o">{</code>
<code class="kt">int</code> <code class="n">val</code><code class="o">;</code>
<code class="k">while</code><code class="o">(</code> <code class="o">(</code><code class="n">val</code><code class="o">=</code><code class="n">System</code><code class="o">.</code><code class="na">in</code><code class="o">.</code><code class="na">read</code><code class="o">())</code> <code class="o">!=</code> <code class="o">-</code><code class="mi">1</code> <code class="o">)</code>
<code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">((</code><code class="kt">byte</code><code class="o">)</code><code class="n">val</code><code class="o">);</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">IOException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code></pre><p>As we’ve shown in the examples, the <code class="literal">read()</code> method can also throw an <a id="I_indexterm12_id751547" class="indexterm"/><code class="literal">IOException</code> if there is
an error reading from the underlying stream source. Various subclasses
of <code class="literal">IOException</code> may indicate that a
source such as a file or network connection has had an error.
Additionally, higher-level streams that read data types more complex
than a single byte may throw <code class="literal">EOFException</code> (“end of file”), which indicates
an unexpected or premature end of stream.</p><p>An overloaded form of <code class="literal">read()</code>
fills a byte array with as much data as possible up to the capacity of
the array and returns the number of bytes read:</p><a id="I_12_tt764"/><pre class="programlisting"> <code class="kt">byte</code> <code class="o">[]</code> <code class="n">buff</code> <code class="o">=</code> <code class="k">new</code> <code class="kt">byte</code> <code class="o">[</code><code class="mi">1024</code><code class="o">];</code>
<code class="kt">int</code> <code class="n">got</code> <code class="o">=</code> <code class="n">System</code><code class="o">.</code><code class="na">in</code><code class="o">.</code><code class="na">read</code><code class="o">(</code> <code class="n">buff</code> <code class="o">);</code></pre><p>In theory, we can also check the number of bytes available for
reading at a given time on an <code class="literal">InputStream</code> using the <code class="literal">available()</code> method. With that information, we
could create an array of exactly the right size:</p><a id="I_12_tt765"/><pre class="programlisting"> <code class="kt">int</code> <code class="n">waiting</code> <code class="o">=</code> <code class="n">System</code><code class="o">.</code><code class="na">in</code><code class="o">.</code><code class="na">available</code><code class="o">();</code>
<code class="k">if</code> <code class="o">(</code> <code class="n">waiting</code> <code class="o">></code> <code class="mi">0</code> <code class="o">)</code> <code class="o">{</code>
<code class="kt">byte</code> <code class="o">[]</code> <code class="n">data</code> <code class="o">=</code> <code class="k">new</code> <code class="kt">byte</code> <code class="o">[</code> <code class="n">waiting</code> <code class="o">];</code>
<code class="n">System</code><code class="o">.</code><code class="na">in</code><code class="o">.</code><code class="na">read</code><code class="o">(</code> <code class="n">data</code> <code class="o">);</code>
<code class="o">...</code>
<code class="o">}</code></pre><p>However, the reliability of this technique depends on the ability
of the underlying stream implementation to detect how much data can be
retrieved. It generally works for files but should not be relied upon
for all types of streams.</p><p>These <code class="literal">read()</code> methods block
until at least some data is read (at least one byte). You must, in
general, check the returned value to determine how much data you got and
if you need to read more. (We look at nonblocking I/O later in this
chapter.) The <a id="I_indexterm12_id751630" class="indexterm"/><code class="literal">skip()</code> method of
<code class="literal">InputStream</code> provides a way of jumping
over a number of bytes. Depending on the implementation of the stream,
skipping bytes may be more efficient than reading them.</p><p>The <a id="I_indexterm12_id751649" class="indexterm"/><code class="literal">close()</code> method shuts
down the stream and frees up any associated system resources. It’s
important for performance to remember to close most types of streams
when you are finished using them. In some cases, streams may be closed
automatically when objects are garbage-collected, but it is not a good
idea to rely on this behavior. In Java 7, the <span class="emphasis"><em><code class="literal">try</code>-with-resources</em></span> language feature
was added to make automatically closing streams and other closeable
entities easier. We’ll see some examples of that later in this chapter.
The flag interface <code class="literal">java.io.Closeable</code>
identifies all types of stream, channel, and related utility classes
that can be closed.</p><p>Finally, we should mention that in addition to the <code class="literal">System.in</code> and <code class="literal">System.out</code> standard streams, Java provides the
<code class="literal">java.io.Console</code> API through <code class="literal">System.console()</code>. You can use the <code class="literal">Console</code> to read passwords without echoing them
to the screen.<a id="I_indexterm12_id751714" class="indexterm"/><a id="I_indexterm12_id751721" class="indexterm"/></p></div><div class="sect2" title="Character Streams"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-12-SECT-1.2"/>Character Streams</h2></div></div></div><p><a id="idx10686" class="indexterm"/> <a id="idx10722" class="indexterm"/> <a id="idx10751" class="indexterm"/>In early versions of Java, some <code class="literal">InputStream</code> and <code class="literal">OutputStream</code> types included methods for
reading and writing strings, but most of them operated by naively
assuming that a 16-bit Unicode character was equivalent to an 8-bit byte
in the stream. This works only for Latin-1 (ISO 8859-1) characters and
not for the world of other encodings that are used with different
languages. In <a class="xref" href="ch10.html" title="Chapter 10. Working with Text">Chapter 10</a>, we saw that the
<code class="literal">java.lang.String</code> class has a byte
array constructor and a corresponding <code class="literal">getBytes()</code> method that each accept character
encoding as an argument. In theory, we could use these as tools to
transform arrays of bytes to and from Unicode characters so that we
could work with byte streams that represent character data in any
encoding format. Fortunately, however, we don’t have to rely on this
because Java has streams that handle this for us.</p><p>The <code class="literal">java.io Reader</code> and <code class="literal">Writer</code> character stream classes were
introduced as streams that handle character data only. When you use
these classes, you think only in terms of characters and string data and
allow the underlying implementation to handle the conversion of bytes to
a specific character encoding. As we’ll see, some direct implementations
of <a id="I_indexterm12_id751828" class="indexterm"/><code class="literal">Reader</code> and <a id="I_indexterm12_id751838" class="indexterm"/><code class="literal">Writer</code> exist, for
example, for reading and writing files. But more generally, two special
classes, <a id="I_indexterm12_id751850" class="indexterm"/><code class="literal">InputStreamReader</code> and
<a id="I_indexterm12_id751861" class="indexterm"/><code class="literal">OutputStreamWriter</code>,
bridge the gap between the world of character streams and the world of
byte streams. These are, respectively, a <code class="literal">Reader</code> and a <code class="literal">Writer</code> that can be wrapped around any
underlying byte stream to make it a character stream. An encoding scheme
is used to convert between possible multibyte encoded values and Java
Unicode characters. An encoding scheme can be specified by name in the
constructor of <code class="literal">InputStreamReader</code> or
<code class="literal">OutputStreamWriter</code>. For convenience,
the default constructor uses the system’s default encoding
scheme.</p><p>For example, let’s parse a human-readable string from the standard
input into an integer. We’ll assume that the bytes coming from
<a id="I_indexterm12_id751903" class="indexterm"/><code class="literal">System.in</code> use the
system’s default encoding scheme:</p><a id="I_12_tt766"/><pre class="programlisting"> <code class="k">try</code> <code class="o">{</code>
<code class="n">InputStream</code> <code class="n">in</code> <code class="o">=</code> <code class="n">System</code><code class="o">.</code><code class="na">in</code><code class="o">;</code>
<code class="n">InputStreamReader</code> <code class="n">charsIn</code> <code class="o">=</code> <code class="k">new</code> <code class="n">InputStreamReader</code><code class="o">(</code> <code class="n">in</code> <code class="o">);</code>
<code class="n">BufferedReader</code> <code class="n">bufferedCharsIn</code> <code class="o">=</code> <code class="k">new</code> <code class="n">BufferedReader</code><code class="o">(</code> <code class="n">inReader</code> <code class="o">);</code>
<code class="n">String</code> <code class="n">line</code> <code class="o">=</code> <code class="n">bufferedCharsIn</code><code class="o">.</code><code class="na">readLine</code><code class="o">();</code>
<code class="kt">int</code> <code class="n">i</code> <code class="o">=</code> <code class="n">NumberFormat</code><code class="o">.</code><code class="na">getInstance</code><code class="o">().</code><code class="na">parse</code><code class="o">(</code> <code class="n">line</code> <code class="o">).</code><code class="na">intValue</code><code class="o">();</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">IOException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code>
<code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">ParseException</code> <code class="n">pe</code> <code class="o">)</code> <code class="o">{</code> <code class="o">}</code></pre><p>First, we wrap an <code class="literal">InputStreamReader</code> around <code class="literal">System.in</code>. This reader converts the incoming
bytes of <code class="literal">System.in</code> to characters
using the default encoding scheme. Then, we wrap a <a id="I_indexterm12_id751946" class="indexterm"/><code class="literal">BufferedReader</code> around
the <code class="literal">InputStreamReader</code>. <code class="literal">BufferedReader</code> adds the <a id="I_indexterm12_id751967" class="indexterm"/><code class="literal">readLine()</code> method,
which we can use to grab a full line of text (up to a platform-specific,
line-terminator character combination) into a <code class="literal">String</code>. The string is then parsed into an
integer using the techniques described in <a class="xref" href="ch10.html" title="Chapter 10. Working with Text">Chapter 10</a>.</p><p>The important thing to note is that we have taken a byte-oriented
input stream, <code class="literal">System.in</code>, and safely
converted it to a <code class="literal">Reader</code> for reading
characters. If we wished to use an encoding other than the system
default, we could have specified it in the <code class="literal">InputStreamReader</code>’s constructor like
so:</p><a id="I_12_tt767"/><pre class="programlisting"> <code class="n">InputStreamReader</code> <code class="n">reader</code> <code class="o">=</code> <code class="k">new</code> <code class="n">InputStreamReader</code><code class="o">(</code> <code class="n">System</code><code class="o">.</code><code class="na">in</code><code class="o">,</code> <code class="s">"UTF-8"</code> <code class="o">);</code></pre><p>For each character that is read from the reader, the <code class="literal">InputStreamReader</code> reads one or more bytes and
performs the necessary conversion to Unicode.</p><p>In <a class="xref" href="ch13.html" title="Chapter 13. Network Programming">Chapter 13</a>, we use an <code class="literal">InputStreamReader</code> and a <code class="literal">Writer</code> in our simple web server example, where
we must use a character encoding specified by the HTTP protocol. We also
return to the topic of character encodings when we discuss the <code class="literal">java.nio.charset</code> API, which allows you to
query for and use encoders and decoders explicitly on buffers of
characters and bytes. Both <code class="literal">InputStreamReader</code> and <code class="literal">OutputStreamWriter</code> can accept a <code class="literal">Charset</code> codec object as well as a character
encoding name.<a id="I_indexterm12_id752071" class="indexterm"/><a id="I_indexterm12_id752078" class="indexterm"/><a id="I_indexterm12_id752085" class="indexterm"/></p></div><div class="sect2" title="Stream Wrappers"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-12-SECT-1.3"/>Stream Wrappers</h2></div></div></div><p><a id="idx10725" class="indexterm"/>What if we want to do more than read and write a sequence
of bytes or characters? We can use a “filter” stream, which is a type of
<code class="literal">InputStream</code>, <code class="literal">OutputStream</code>, <code class="literal">Reader</code>, or <code class="literal">Writer</code> that wraps another stream and adds new
features. A filter stream takes the target stream as an argument in its
constructor and delegates calls to it after doing some additional
processing of its own. For example, we can construct a <a id="I_indexterm12_id752139" class="indexterm"/><code class="literal">BufferedInputStream</code> to
wrap the system standard input:</p><a id="I_12_tt768"/><pre class="programlisting"> <code class="n">InputStream</code> <code class="n">bufferedIn</code> <code class="o">=</code> <code class="k">new</code> <code class="n">BufferedInputStream</code><code class="o">(</code> <code class="n">System</code><code class="o">.</code><code class="na">in</code> <code class="o">);</code></pre><p>The <code class="literal">BufferedInputStream</code> is a
type of filter stream that reads ahead and buffers a certain amount of
data. (We’ll talk more about it later in this chapter.) The <code class="literal">BufferedInputStream</code> wraps an additional layer
of functionality around the underlying stream. <a class="xref" href="ch12s01.html#learnjava3-CHP-12-FIG-3" title="Figure 12-3. Layered streams">Figure 12-3</a> shows this arrangement for a
<a id="I_indexterm12_id752181" class="indexterm"/><code class="literal">DataInputStream</code>, which
is a type of stream that can read higher-level data types, such as Java
primitives and strings.</p><div class="figure"><a id="learnjava3-CHP-12-FIG-3"/><div class="figure-contents"><div class="mediaobject"><a id="I_12_tt769"/><img src="httpatomoreillycomsourceoreillyimages1707642.png" alt="Layered streams"/></div></div><p class="title">Figure 12-3. Layered streams</p></div><p>As you can see from the previous code snippet, the <code class="literal">BufferedInputStream</code> filter is a type of
<code class="literal">InputStream</code>. Because filter streams
are themselves subclasses of the basic stream types, they can be used as
arguments to the construction of other filter streams. This allows
filter streams to be layered on top of one another to provide different
combinations of features. For example, we could first wrap our <code class="literal">System.in</code> with a <code class="literal">BufferedInputStream</code> and then wrap the <code class="literal">BufferedInputStream</code> with a <code class="literal">DataInputStream</code> for reading special data types
with buffering.</p><p>Java provides base classes for creating new types of filter
streams: <a id="I_indexterm12_id752253" class="indexterm"/><code class="literal">FilterInputStream</code>,
<a id="I_indexterm12_id752264" class="indexterm"/><code class="literal">FilterOutputStream</code>,
<a id="I_indexterm12_id752275" class="indexterm"/><code class="literal">FilterReader</code>, and
<a id="I_indexterm12_id752286" class="indexterm"/><code class="literal">FilterWriter</code>. These
superclasses provide the basic machinery for a “no op” filter (a filter
that doesn’t do anything) by delegating all their method calls to their
underlying stream. Real filter streams subclass these and override
various methods to add their additional processing. We’ll make an
example filter stream later in this chapter.</p><div class="sect3" title="Data streams"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-12-SECT-1.3.1"/>Data streams</h3></div></div></div><p><a id="idx10692" class="indexterm"/> <a id="idx10755" class="indexterm"/> <a id="I_indexterm12_id752334" class="indexterm"/> <code class="literal">DataInputStream</code> and
<a id="I_indexterm12_id752346" class="indexterm"/><code class="literal">DataOutputStream</code> are
filter streams that let you read or write strings and primitive data
types composed of more than a single byte. <code class="literal">DataInputStream</code> and <code class="literal">DataOutputStream</code> implement the <a id="I_indexterm12_id752369" class="indexterm"/><code class="literal">DataInput</code> and
<a id="I_indexterm12_id752379" class="indexterm"/><code class="literal">DataOutput</code>
interfaces, respectively. These interfaces define methods for reading
or writing strings and all of the Java primitive types, including
numbers and Boolean values. <code class="literal">DataOutputStream</code> encodes these values in a
machine-independent manner and then writes them to its underlying byte
stream. <code class="literal">DataInputStream</code> does the
converse.</p><p>You can construct a <code class="literal">DataInputStream</code> from an <code class="literal">InputStream</code> and then use a method such as
<a id="I_indexterm12_id752417" class="indexterm"/><code class="literal">readDouble()</code> to read
a primitive data type:</p><a id="I_12_tt770"/><pre class="programlisting"> <code class="n">DataInputStream</code> <code class="n">dis</code> <code class="o">=</code> <code class="k">new</code> <code class="n">DataInputStream</code><code class="o">(</code> <code class="n">System</code><code class="o">.</code><code class="na">in</code> <code class="o">);</code>
<code class="kt">double</code> <code class="n">d</code> <code class="o">=</code> <code class="n">dis</code><code class="o">.</code><code class="na">readDouble</code><code class="o">();</code></pre><p>This example wraps the standard input stream in a <code class="literal">DataInputStream</code> and uses it to read a
<code class="literal">double</code> value. The <code class="literal">readDouble()</code> method reads bytes from the
stream and constructs a <code class="literal">double</code> from
them. The <code class="literal">DataInputStream</code> methods
expect the bytes of numeric data types to be in <span class="emphasis"><em>network byte
order</em></span>, a standard that specifies that the high-order bytes
are sent first (also known as “big endian,” as we discuss
later).</p><p>The <code class="literal">DataOutputStream</code> class
provides write methods that correspond to the read methods in <code class="literal">DataInputStream</code>. For example, <a id="I_indexterm12_id752488" class="indexterm"/><code class="literal">writeInt()</code> writes an
integer in binary format to the underlying output stream.</p><p>The <a id="I_indexterm12_id752501" class="indexterm"/><code class="literal">readUTF()</code> and
<a id="I_indexterm12_id752512" class="indexterm"/><code class="literal">writeUTF()</code> methods of
<code class="literal">DataInputStream</code> and <code class="literal">DataOutputStream</code> read and write a Java
<code class="literal">String</code> of Unicode characters using
the UTF-8 “transformation format” character encoding. UTF-8 is an
ASCII-compatible encoding of Unicode characters that is very widely
used. Not all encodings are guaranteed to preserve all Unicode
characters, but UTF-8 does. You can also use UTF-8 with <code class="literal">Reader</code> and <code class="literal">Writer</code> streams by specifying it as the
encoding name.<a id="I_indexterm12_id752556" class="indexterm"/><a id="I_indexterm12_id752563" class="indexterm"/></p></div><div class="sect3" title="Buffered streams"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-12-SECT-1.3.2"/>Buffered streams</h3></div></div></div><p><a id="idx10680" class="indexterm"/> <a id="idx10754" class="indexterm"/>The <a id="I_indexterm12_id752602" class="indexterm"/><code class="literal">BufferedInputStream</code>,
<a id="I_indexterm12_id752613" class="indexterm"/><code class="literal">BufferedOutputStream</code>,
<a id="I_indexterm12_id752624" class="indexterm"/><code class="literal">BufferedReader</code>, and
<a id="I_indexterm12_id752634" class="indexterm"/><code class="literal">BufferedWriter</code>
classes add a data buffer of a specified size to the stream path. A
buffer can increase efficiency by reducing the number of physical read
or write operations that correspond to <a id="I_indexterm12_id752647" class="indexterm"/><code class="literal">read()</code> or <a id="I_indexterm12_id752657" class="indexterm"/><code class="literal">write()</code> method calls.
You create a buffered stream with an appropriate input or output
stream and a buffer size. (You can also wrap another stream around a
buffered stream so that it benefits from the buffering.) Here’s a
simple buffered input stream called <code class="literal">bis</code>:</p><a id="I_12_tt771"/><pre class="programlisting"> <code class="n">BufferedInputStream</code> <code class="n">bis</code> <code class="o">=</code> <code class="k">new</code> <code class="n">BufferedInputStream</code><code class="o">(</code><code class="n">myInputStream</code><code class="o">,</code> <code class="mi">32768</code><code class="o">);</code>
<code class="o">...</code>
<code class="n">bis</code><code class="o">.</code><code class="na">read</code><code class="o">();</code></pre><p>In this example, we specify a buffer size of 32 KB. If we leave
off the size of the buffer in the constructor, a reasonably sized one
is chosen for us. (Currently the default is 8 KB.) On our first call
to <code class="literal">read()</code>, <code class="literal">bis</code> tries to fill our entire 32 KB buffer
with data, if it’s available. Thereafter, calls to <code class="literal">read()</code> retrieve data from the buffer, which
is refilled as necessary.</p><p>A <code class="literal">BufferedOutputStream</code> works
in a similar way. Calls to <code class="literal">write()</code>
store the data in a buffer; data is actually written only when the
buffer fills up. You can also use the <a id="I_indexterm12_id752724" class="indexterm"/><code class="literal">flush()</code> method to
wring out the contents of a <code class="literal">BufferedOutputStream</code> at any time. The
<code class="literal">flush()</code> method is actually a method
of the <code class="literal">OutputStream</code> class itself.
It’s important because it allows you to be sure that all data in any
underlying streams and filter streams has been sent (before, for
example, you wait for a response).</p><p>Some input streams such as <code class="literal">BufferedInputStream</code> support the ability to
mark a location in the data and later reset the stream to that
position. The <a id="I_indexterm12_id752764" class="indexterm"/><code class="literal">mark()</code> method sets
the return point in the stream. It takes an integer value that
specifies the number of bytes that can be read before the stream gives
up and forgets about the mark. The <a id="I_indexterm12_id752776" class="indexterm"/><code class="literal">reset()</code> method
returns the stream to the marked point; any data read after the call
to <code class="literal">mark()</code> is read again.</p><p>This functionality could be useful when you are reading the
stream in a parser. You may occasionally fail to parse a structure and
so must try something else. In this situation, you can have your
parser generate an error and then reset the stream to the point before
it began parsing the structure:</p><a id="I_12_tt772"/><pre class="programlisting"> <code class="n">BufferedInputStream</code> <code class="n">input</code><code class="o">;</code>
<code class="o">...</code>
<code class="k">try</code> <code class="o">{</code>
<code class="n">input</code><code class="o">.</code><code class="na">mark</code><code class="o">(</code> <code class="n">MAX_DATA_STRUCTURE_SIZE</code> <code class="o">);</code>
<code class="k">return</code><code class="o">(</code> <code class="n">parseDataStructure</code><code class="o">(</code> <code class="n">input</code> <code class="o">)</code> <code class="o">);</code>
<code class="o">}</code>
<code class="k">catch</code> <code class="o">(</code> <code class="n">ParseException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code>
<code class="n">input</code><code class="o">.</code><code class="na">reset</code><code class="o">();</code>
<code class="o">...</code>
<code class="o">}</code></pre><p>The <code class="literal">BufferedReader</code> and
<code class="literal">BufferedWriter</code> classes work just
like their byte-based counterparts, except that they operate on
characters instead of bytes.<a id="I_indexterm12_id752822" class="indexterm"/><a id="I_indexterm12_id752829" class="indexterm"/></p></div><div class="sect3" title="PrintWriter and PrintStream"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-12-SECT-1.3.3"/>PrintWriter and PrintStream</h3></div></div></div><p><a id="idx10744" class="indexterm"/> <a id="idx10745" class="indexterm"/> <a id="idx10756" class="indexterm"/>Another useful wrapper stream is <code class="literal">java.io.PrintWriter</code>. This class provides a
suite of overloaded <code class="literal">print()</code> methods
that turn their arguments into strings and push them out the stream. A
complementary set of <code class="literal">println()</code>
convenience methods appends a new line to the end of the strings. For
formatted text output, <a id="I_indexterm12_id752898" class="indexterm"/><code class="literal">printf()</code> and the
identical <code class="literal">format()</code> methods allow
you to write <code class="literal">printf</code>-style formatted
text to the stream.</p><p><code class="literal">PrintWriter</code> is an unusual
character stream because it can wrap either an <code class="literal">OutputStream</code> or another <code class="literal">Writer</code>. <code class="literal">PrintWriter</code> is the more capable big brother
of the legacy <code class="literal">PrintStream</code> byte
stream. The <code class="literal">System.out</code> and <code class="literal">System.err</code> streams are <code class="literal">PrintStream</code> objects; you have already seen
such streams strewn throughout this book:</p><a id="I_12_tt773"/><pre class="programlisting"> <code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">print</code><code class="o">(</code><code class="s">"Hello, world...\n"</code><code class="o">);</code>
<code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code><code class="s">"Hello, world..."</code><code class="o">);</code>
<code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">printf</code><code class="o">(</code><code class="s">"The answer is %d"</code><code class="o">,</code> <code class="mi">17</code> <code class="o">);</code>
<code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code> <code class="mf">3.14</code> <code class="o">);</code></pre><p>Early versions of Java did not have the <code class="literal">Reader</code> and <code class="literal">Writer</code> classes and used <code class="literal">PrintStream</code>, which convert bytes to
characters by simply made assumptions about the character encoding.
You should use a <code class="literal">PrintWriter</code> for
all new development.</p><p>When you create a <code class="literal">PrintWriter</code>
object, you can pass an additional Boolean value to the constructor,
specifying whether it should “auto-flush.” If this value is <code class="literal">true</code>, the <code class="literal">PrintWriter</code> automatically performs a
<code class="literal">flush()</code> on the underlying <code class="literal">OutputStream</code> or <code class="literal">Writer</code> each time it sends a newline:</p><a id="I_12_tt774"/><pre class="programlisting"><code class="n">PrintWriter</code> <code class="n">pw</code> <code class="o">=</code> <code class="k">new</code> <code class="n">PrintWriter</code><code class="o">(</code> <code class="n">myOutputStream</code><code class="o">,</code> <code class="kc">true</code> <code class="cm">/*autoFlush*/</code> <code class="o">);</code>
<code class="n">pw</code><code class="o">.</code><code class="na">println</code><code class="o">(</code><code class="s">"Hello!"</code><code class="o">);</code> <code class="c1">// Stream is automatically flushed by the newline.</code></pre><p>When this technique is used with a buffered output stream, it
corresponds to the behavior of terminals that send data line by
line.</p><p>The other big advantage that print streams have over regular
character streams is that they shield you from exceptions thrown by
the underlying streams. Unlike methods in other stream classes, the
methods of <code class="literal">PrintWriter</code> and <code class="literal">PrintStream</code> do not throw <code class="literal">IOException</code>s. Instead, they provide a method
to explicitly check for errors if required. This makes life a lot
easier for printing text, which is a very common operation. You can
check for errors with the <a id="I_indexterm12_id753072" class="indexterm"/><code class="literal">checkError()</code>
method:<a id="I_indexterm12_id753083" class="indexterm"/><a id="I_indexterm12_id753090" class="indexterm"/><a id="I_indexterm12_id753097" class="indexterm"/><a id="I_indexterm12_id753104" class="indexterm"/></p><a id="I_12_tt775"/><pre class="programlisting"> <code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code> <code class="n">reallyLongString</code> <code class="o">);</code>
<code class="k">if</code> <code class="o">(</code> <code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">checkError</code><code class="o">()</code> <code class="o">){</code> <code class="o">...</code> <code class="c1">// uh oh</code></pre></div></div><div class="sect2" title="Pipes"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-12-SECT-1.4"/>Pipes</h2></div></div></div><p><a id="idx10724" class="indexterm"/> <a id="idx10743" class="indexterm"/> <a id="idx10753" class="indexterm"/>Normally, our applications are directly involved with one
side of a given stream at a time. <a id="I_indexterm12_id753166" class="indexterm"/><code class="literal">PipedInputStream</code> and
<a id="I_indexterm12_id753177" class="indexterm"/><code class="literal">PipedOutputStream</code> (or
<code class="literal">PipedReader</code> and <code class="literal">PipedWriter</code>), however, let us create two sides
of a stream and connect them, as shown in <a class="xref" href="ch12s01.html#learnjava3-CHP-12-FIG-4" title="Figure 12-4. Piped streams">Figure 12-4</a>. This can be used to provide a
stream of communication between threads, for example, or as a “loopback”
for testing. Often it’s used as a crutch to interface a stream-oriented
API to a non-stream-oriented API.</p><div class="figure"><a id="learnjava3-CHP-12-FIG-4"/><div class="figure-contents"><div class="mediaobject"><a id="I_12_tt776"/><img src="httpatomoreillycomsourceoreillyimages1707643.png" alt="Piped streams"/></div></div><p class="title">Figure 12-4. Piped streams</p></div><p>To create a bytestream pipe, we use both a <code class="literal">PipedInputStream</code> and a <code class="literal">PipedOutputStream</code>. We can simply choose a side
and then construct the other side using the first as an argument:</p><a id="I_12_tt777"/><pre class="programlisting"> <code class="n">PipedInputStream</code> <code class="n">pin</code> <code class="o">=</code> <code class="k">new</code> <code class="n">PipedInputStream</code><code class="o">();</code>
<code class="n">PipedOutputStream</code> <code class="n">pout</code> <code class="o">=</code> <code class="k">new</code> <code class="n">PipedOutputStream</code><code class="o">(</code> <code class="n">pin</code> <code class="o">);</code></pre><p>Alternatively:</p><a id="I_12_tt778"/><pre class="programlisting"> <code class="n">PipedOutputStream</code> <code class="n">pout</code> <code class="o">=</code> <code class="k">new</code> <code class="n">PipedOutputStream</code><code class="o">();</code>
<code class="n">PipedInputStream</code> <code class="n">pin</code> <code class="o">=</code> <code class="k">new</code> <code class="n">PipedInputStream</code><code class="o">(</code> <code class="n">pout</code> <code class="o">);</code></pre><p>In each of these examples, the effect is to produce an input
stream, <code class="literal">pin</code>, and an output stream,
<code class="literal">pout</code>, that are connected. Data
written to <code class="literal">pout</code> can then be read by
<code class="literal">pin</code>. It is also possible to create
the <code class="literal">PipedInputStream</code> and the <code class="literal">PipedOutputStream</c