Just as Java provides a set of classes for reading and writing to and from byte streams, it also provides interfaces and classes for reading and writing to and from character streams. The InputStream and OutputStream counterparts that read character streams are the java.io.Reader and java.io.Writer classes. These classes are responsible for properly converting each character from its encoding scheme of the native OS to Unicode; they are sensitive to different character-encoding schemes and support international applications. Figure 12.2 shows the inheritance hierarchy for the Reader and Writer classes. Figure 12.2. Reader and Writer inheritance hierarchy. Table 12.3 shows a summary of the reader and writer classes: Table 12.3. Reader and Writer Classes Class | Description |
---|
FileReader | Character-oriented counterpart to FileInputStream. | FileWriter | Character-oriented counterpart to FileOutputStream. | InputStreamReader | Converts InputStream objects to Readers. | OutputStreamWriter | Converts OutputStream objects to Writers. | BufferedReader | Reader that uses a buffer for efficiency. | CharArrayReader | Reads an array of characters as a Reader object. | StringReader | Reads a String as a Reader object. | PipedReader | Used for communicating between threads. | BufferedWriter | Writer that uses a buffer for efficiency. | CharArrayWriter | Outputs to a char[]. | StringWriter | Writes to a StringBuffer as a Writer object. | PipedWriter | Other half of thread communications. | PrintWriter | Character equivalent to PrintStream. | Table 12.4 shows the Reader methods, and Table 12.5 shows the Writer methods. Table 12.4. java.io.Reader Methods Method | Description |
---|
abstract void close() | Closes the stream | void mark(int readAheadLimit) | Marks the present position in the stream | boolean markSupported() | Tells whether this stream supports the mark() operation | int read() | Reads a single character | int read(char[] cbuf) | Reads characters into an array | abstract int read(char[] cbuf, int off, int len) | Reads characters into a portion of an array | boolean ready() | Tells whether this stream is ready to be read | void reset() | Resets the stream | long skip(long n) | Skips characters | The Reader class provides methods to read characters, skip over characters, set marks that you can jump back to in the stream (if they are supported), and a method to close the Reader. Table 12.5. java.io.Writer Methods Method | Description |
---|
abstract void close() | Closes the stream, flushing it first | abstract void flush() | Flushes the stream | void write(char[] cbuf) | Writes an array of characters | abstract void write(char[] cbuf, int off, int len) | Writes a portion of an array of characters | void write(int c) | Writes a single character | void write(String str) | Writes a string | void write(String str, int off, int len) | Writes a portion of a string | The Writer class provides three types of methods: methods to write data to a stream, a method to flush data that has been written to the stream, and a method to close the stream. File I/O with Readers/Writers Java provides two classes for reading from and writing to files: java.io.FileReader java.io.FileWriter The FileReader and FileWriter classes can be used almost identically to the FileInputStream and FileOutputStream classes. Listing 12.3 shows an example using these classes. Listing 12.3 FileReaderWriterExample.java import java.io.Reader; import java.io.Writer; import java.io.FileReader; import java.io.FileWriter; public class FileReaderWriterExample { public static void main( String[] args ) { try { Reader r = new FileReader( "in.txt" ); Writer w = new FileWriter( "out.txt" ); int c; while( ( c = r.read() ) != -1 ) { System.out.print( ( char )c ); w.write( c ); } r.close(); w.close(); } catch( Exception e ) { e.printStackTrace(); } } } As you can see this class is almost identical to the stream version except that it uses the reader and writer classes. This example uses the Reader and Writer base classes to read from and write to the FileReader and FileWriter instances. Byte and Character I/O Classes Java provides some helper classes for reading input stream classes as readers and writing to output streams as writers. These two classes are You can use these classes by passing existing streams to their constructors. For example: InputStream is = new FileInputStream( "in.txt" ); Reader r = new InputStreamReader( is ); ...use r... Other Character I/O Reader and Writer Classes Similar to the BufferedInputStream and BufferedOutputStream, character readers have a BufferedReader class and a BufferedWriter class. The BufferedReader class not only provides a more efficient mechanism for reading data from a stream, it also provides a very useful method for reading text: readLine(). This method returns a new line delimited String from the stream. So, you can read an entire stream line by line as follows: BufferedReader br = new BufferedReader( new FileReader( "in.txt" ) ); String line = br.readLine(); while( line != null ) { System.out.println( line ); line = br.readLine(); } Java provides two readers and two writers that are helpful for reading and writing existing data from and to Readers and Writers: CharArrayReader: Allows you to read a character array (char[]) as a Reader. CharArrayWriter: Allows you to write Writers to a character array (char[]). StringReader: Allows you to read a String as a Reader. StringWriter: Allows you to write a Writer to a String. To help write Writer data using print() and println() methods, Java provides the java.io.PrintWriter class. Most commonly, text files are read using the BufferedReader class because you can read one line at a time and text files are written to using the PrintWriter class because it has the familiar print() and println() methods. The last category of readers and writers are the java.io.PipedReader and java.io.PipedWriter classes. These are used for communicating between two processes. StreamTokenizer The java.io.StreamTokenizer class is a utility class to help you parse Readers by dividing them into tokens; you can ask for each white-space delimited String to be returned to you from the Reader. You can think of this as returning the Reader word by word. The StreamTokenizer is a somewhat different to use than most of the classes you have seen thus far. It parses tokens one by one returning a status to tell you if you are at the end of the Reader, and then makes the value available as a public attribute of the StreamTokenizer class (sval). Listing 12.4 shows an example using the StreamTokenizer class to read the in.txt file word by word. Listing 12.4 StreamTokenizerExample.java import java.io.Reader; import java.io.FileReader; import java.io.StreamTokenizer; public class StreamTokenizerExample { public static void main( String[] args ) { try { Reader r = new FileReader( "in.txt" ); StreamTokenizer st = new StreamTokenizer( r ); while( st.nextToken() != StreamTokenizer.TT_EOF ) { System.out.println( st.sval ); } r.close(); } catch( Exception e ) { e.printStackTrace(); } } } Notice from Listing 12.4 that the StreamTokenizer class gets the next token by calling the nextToken() method. This method returns one of the following status values: TT_EOF: Indicates that the end of the stream has been read TT_EOL: Indicates that the end of the line has been read TT_NUMBER: Indicates that a number token has been read TT_WORD: Indicates that a word token has been read Thus, the example reads each token until it reaches the end of the stream (TT_EOF). Accessing the StreamTokenizer's sval public attribute retrieves the String value retrieved by the StreamTokenizer. |