Readers and Writers

     

Java provides a separate set of parent classes for doing character I/O, as opposed to byte IO that is implemented with streams.

Reader is an abstract class, very similar to InputStream. You don't use a reader directly, but rather a different subclass, depending on the source of the characters you need to read.

Writer is also an abstract class, very similar to OutputStream, and its implementing subclasses are used for writing out character data.

Character data comes encoded as a certain character set representation. So let's take a quick detour here before getting into Readers and Writers.

Character Encoding

FileReader and FileWriter read and write double-byte characters. But many native file systems are based on single-byte characters. These streams will utilize the default character encoding scheme of the file system.

To get the default character encoding, check the following property:

 

 System.getProperty("file.encoding") 

You can specify an encoding other than the default. To do this, create an InputStreamReader on a FileInputStream (to read) or OutputStreamWriter on a FileOutputStream (to write) and specify the encoding you want to use. Let's do an example of how to read ISO-Latin-1 or UTF-8 Encoded Data.

 

 //String enc = "8859_1"; //ISO-Latin-1 String enc = "UTF8"; //UTF 8 try { BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream("myFile"), enc));         String line = in.readLine();     } catch (UnsupportedEncodingException e) { //handle     } catch (IOException e) { //handle     } 

Note that the constructor for FileInputStream is overloaded to accept a String containing the charset name , or a charset object, or a CharsetDecoder object. After we construct the FileInputStream object, we pass it as an argument to the InputStreamReader, and then pass that to the BufferedReader constructor, and work with the buffered reader.

You can also call the getEncoding() method to determine what charset is being used by this stream.

Charset

A charset is a combination of a defined set of character codes, and a scheme for encoding the characters into the codes. As we have seen, you can use various charsets when working with file input/output.

Every JVM implementation must support the following charsets:

US-ASCII Seven-bit ASCII, the Basic Latin block of the Unicode character set

ISO-8859-1, ISO-LATIN-1

UTF-8 Eight-bit UCS Transformation Format

UTF-16BE Sixteen-bit UCS Transformation Format, big-endian byte order

UTF-16LE Sixteen-bit UCS Transformation Format, little-endian byte order

UTF-16 Sixteen-bit UCS Transformation Format, byte order identified by an optional byte-order mark

Reader

The implementing subclasses of reader that you might use are illuminated in the following sections.

BufferedReader

This guy is perhaps the most popular reader, and for good reason. He's fiendishly handsome, plays a surprisingly smoking clarinet, and isn't afraid to kegstand character data when pressed to. There are other reasons too. To begin with, BufferedReader provides access to each individual line in a file. The other readers don't. So if you're reading data from a log file, a csv file, or other such source, this is probably your best choice.

Also impressive is that the BufferedReader is buffered. That means that it provides very efficient reading of characters, arrays, and lines. You can specify the buffer size you prefer if you don't like the default, which is usually large enough.

Here is a typical use of BufferedReader:

 

 BufferedReader input    = new BufferedReader(new FileReader("myInputFile.txt ")); 

Here's what's happening. You construct a FileReader object, passing it the String name of the file you want to read. You pass this newly minted FileReader object to the BufferedReader constructor, and call it "input." You can then read the data in one of three ways.

Call input.readLine() to access a single line of character data. A line is considered to be terminated by either a line feed ( \n ), a carriage return ( \r ), or a carriage return followed immediately by a line feed. This method will return null after it reaches the end of the stream. So you can read every line of a file like this:

 

 String line = ""; while ((line = in.readLine()) != null)     //do something with line } //eof 

The loop looks a little busy because we're doing two things: checking if we reached the end of the file, and then assigning the current line of character data to the "line" string variable so that we can do something with it inside the loop. That line will be set to null when the end of the file is reached.

Call input.read() to read a single character.

Call input.read(char[] cbuf, int off, int len) to read characters into a portion of an array. This method repeatedly invokes the read() method of the underlying stream until one of the following happens:

  1. The number of characters specified in the len parameter have been read.

  2. The underlying read() method returns “1, which indicates the end of file has been reached.

  3. The ready() method returns false, indicating any further calls to read() would block.

CharArrayReader and StringReader

These classes are useful when the character data source is an array or String.

FileReader

Useful when the character data source is a File. Wrap it in a BufferedReader for freshest taste.

InputStreamReader

Use this class when the character source is an InputStream. It allows any input stream type to be used with characters instead of bytes. Here's the basic recipe for reading lines of characters from an input stream:

  1. Create your input stream type based on the byte source.

  2. Create InputStreamReader object using that input source.

  3. Create BufferedReader object from that input stream reader.

  4. Call readLine() method. Returns a non-terminated String.

  5. Process yer data.

  6. Repeat until readLine() returns null .

  7. Take the day off and go to a yachting festival.

Writer

Writer subclasses work the same way as reader subclasses do.

BufferedWriter

Efficiently writes character text to an output stream using a buffer. The BufferedWriter provides a newLine() method, which uses the system-dependent character for a new line as defined by the system property line separator.

Because many Writers send their data directly to the underlying stream, it is a good idea to wrap a BufferedWriter class around a FileWriter or OutputStreamWriter, much as we did with BufferedReader.

 

 try {         BufferedWriter out = new BufferedWriter(new FileWriter("outFile.txt"));         out.write("some data");         out.close();     } catch (IOException e) {        //handle     } 

In the preceding example, the file outFile.txt will be created if it does not already exist.

If you want to append character data to the end of a file that already exists, pass a Boolean true as a second argument to the FileWriter constructor, as in the following example:

 

 BufferedWriter out = new BufferedWriter(new FileWriter("outFile.txt", true)); 

Note that you can call the flush() method to flush the buffer should it be necessary to manually do so.

OutputStreamWriter

This class serves as a bridge between character and byte stream classes. Its purpose is to encode the characters written to this stream as bytes of the specified charset.

Each time you call the write() method, the charset encoder is invoked on the given characters, and are sent to a buffer. The data is then written to the underlying output stream.

PipedWriter

This class is the companion to PipedReader, mentioned previously. A typical constructor specifies the name of the PipedReader to synch to.

Note that while there is a no-arg constructor for this class, it must be connected to a PipedReader before it can be used. Do so using the connect(PipedReader pr) method. If the PipedWriter is already connected to a PipedReader, an IOException is thrown.

Let's look at some code that puts this to work.

Reading Text from a File

Here is a class that you can likely use with some frequency. It reads in a text file line by line and calls a processing method as it does so. For this example, the processing method simply sends all of the characters to uppercase and prints it to the console.

ReadingTextFromFile.java
 

 package net.javagarage.demo.io.files; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; /**<p>  * This code reads in a file line by line  * with BufferedReader and processes each  * line.  * @author Eben Hewitt  **/ public class ReadingTextFromFile { public static void main(String[] args) { read("C:\readtest.txt"); } //convenience method to encapsulate //the work of reading data. public static void read(String fileName) {       try {             BufferedReader in = new BufferedReader(new FileReader(fileName));             String line;             int count = 0;             while ((line = in.readLine()) != null) {                 //our own method to do something                 handle(line);                 //count each line                 count++;             }             in.close();             //show total at the end of file             log("Lines read: " + count);       } catch (IOException e) {             log(e.getMessage());       } } //does the work on every line as it is //read in by our read method private static void handle(String line){       //just send characters to upper case       //and print to System.out       log(line.toUpperCase()); } //convenience to save typing, keep focus private static void log(String msg){       System.out.println(">" + msg); } } 

The output from the file is a result that has all characters in uppercase text, a ? string pointing to every line ”whether is has data on it or not ”and then the total number of lines read in, as in the following:

 

 //blah blah blah >EXECUTING ACTIONS > >EXECUTING ACTION: INSTALLDRVRMGR > ARG1: '(NULL)' > ARG2: '(NULL)' > ARGS: '' >INSTALL DRIVER MANAGER SUCCEEDED > RETURN HR: 0X0 > >Lines read: 31 

Writing Text to a File

This class writes character data to a file. If the file does not exist, it is created. If it does exist and has data in it, any new data is appended to the end of the file.

WritingTextToFile.java
 

 package net.javagarage.demo.io.files; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Date; /**<p>  * This code reads in a file line by line  * with BufferedReader and processes each  * line.  * @author Eben Hewitt  **/ public class WritingTextToFile { public static void main(String[] args) { write("C:\writetest.log"); log("All done."); } //convenience method to encapsulate //the work of reading data. public static void write(String fileName) { try { BufferedWriter out = new BufferedWriter(new FileWriter(fileName, true)); out.write("GMT Date:"); out.newLine(); out.write(new Date().toGMTString()); out.close(); } catch (UnsupportedEncodingException uee) { log(uee.getMessage()); } catch (IOException ioe) { log(ioe.getMessage()); } } //convenience to save typing, keep focus private static void log(String msg){ System.out.println(">" + msg); } } 

The result simply prints

 

 > All done. 

And when you open the written file, it contains data similar to the following:

 

 GMT Date: 27 Mar 2004 23:27:16 GMT 

Reading and Writing Image Data

To find out how to read and write Image data, you can do two things. Check out the following classes in the 1.5.0 API.

The second thing is to look in the example code I've written in the toolbox section of the garage. The GaragePad app lets you draw freehand onto the canvas and then save the pixel data into an image.

Okay. That sounds kind of lame. So here is a sneak preview:

 

 Image image = canvas.createImage(rect.width, rect.height); Graphics g = image.getGraphics(); canvas.paint(g); ImageIO.write((RenderedImage)image, "jpg", outFile); 

This code uses the write method of the javax.imageio.ImageIO class to write out a new file with JPEG encoding, and it will be called whatever the value of outFile is. To do so, it creates a java.awt.Image object from a java.awt.Canvas object, which captures the drawn pixels.



Java Garage
Java Garage
ISBN: 0321246233
EAN: 2147483647
Year: 2006
Pages: 228
Authors: Eben Hewitt

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net