UNPKG

epubjs

Version:

Render ePub documents in the browser, across many devices

345 lines (344 loc) 73.3 kB
<?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=&quot;pat” timestamp=&quot;20121117T215954-0600” comment=&quot;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">&gt;</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