Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ganesh_JavaSE7_Programming_1z0-804_study_guide.pdf
Скачиваний:
94
Добавлен:
02.02.2015
Размер:
5.88 Mб
Скачать

Chapter 8 Java I/O Fundamentals

Character Streams and Byte Streams

Consider the difference between Java source files and class files generated by the compiler. The Java source files have extension of .java and are meant to be read by humans as well as programming tools such as compilers. However, the Java class files have extension of .class and are not meant to be read by humans; they are meant to be processed by low-level tools such as a JVM (executable java.exe in Windows) and Java disassember (executable javap.exe

in Windows). We refer to human-readable files containing text (or characters) as text files; we refer to the machine readable or low-level data storage files as binary files. Naturally, how you interpret what is inside text files vs. binary files is different. For example, in text files, you can interpret the data read from the file and differentiate between a tab character, whitespace character, newline character, etc. However, you don’t deal with data from binary files like that; they are low-level values. To give another example, consider a .txt file you create with a text editor such as Notepad in Windows; it contains human-readable text. Now, consider storing your photo in a .bmp or .jpeg file; these files are certainly not human readable. They are meant for processing by photo editing or image manipulation software, and the files contain data in some pre-determined low-level format.

The java.io package has classes that support both character streams and byte streams. You can use character streams for text-based I/O. Byte streams are used for data-based I/O. Character streams for reading and writing are called readers and writers, respectively (represented by the abstract classes of Reader and Writer). Byte streams for reading and writing are called input streams and output streams, respectively (represented by the abstract classes of InputStream and OutputStream). Table 8-2 summarizes the differences between character streams and byte streams for your quick reference.

Table 8-2.  Differences Between Character Streams and Byte Streams

Character streams

Byte streams

Meant for reading or writing to characteror text-based I/O such as text files, text documents, XML, and HTML files.

Data dealt with is 16-bit Unicode characters.

Input and output character streams are called readers and writers, respectively.

The abstract classes of Reader and Writer and their derived classes in the java.io package provide support for character streams.

Meant for reading or writing to binary data I/O such as executable files, image files, and files in low-level file formats such as .zip, .class, .obj, and .exe.

Data dealt with is bytes (i.e., units of 8-bit data).

Input and output byte streams are simply called input streams and output streams, respectively.

The abstract classes of InputStream and OutputStream and their derived classes in the java.io package provide support for byte streams.

If you try using a byte stream when a character stream is needed and vice versa, you’ll get a nasty surprise in your programs. For example, a bitmap (.bmp) image file must be processed using a byte stream; if you try using character stream, your program won’t work. So don’t mix up the streams!

Character Streams

In this section, you’ll explore I/O with character streams. You’ll learn how to read from and write to text files plus some optional features such as buffering to speed up the I/O. For reading and writing text files, you can use the classes derived from the Reader and Writer abstract classes, respectively. For character streams, Figure 8-2 shows important Reader classes, and Table 8-3 provides a short description of these classes. Figure 8-3 shows important Writer classes, and Table 8-4 provides a short description of these classes. Note that we’ll cover only a few important classes in this class hierarchy in this chapter.

230

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Chapter 8 Java I/O Fundamentals

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Reader

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BufferedReader

 

 

FilterReader

 

 

 

PipedReader

 

 

InputStreamReader

 

 

StringReader

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

LineNumberReader

 

PushbackReader

 

 

 

 

 

 

FileReader

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Figure 8-2.  Important classes deriving from the Reader class

 

 

 

Table 8-3.  Important Classes Deriving from the Reader Class

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Class name

 

 

Short description

 

 

 

 

 

 

 

 

 

 

StringReader

 

 

A character stream that operates on strings.

 

 

 

InputStreamReader

 

 

This class is a bridge between character streams and byte streams.

FileReader

 

 

Derived class of InputStreamReader that provides support for reading character files.

PipedReader

 

 

The PipedReader and PipedWriter classes form a pair for “piped” reading/writing

 

 

 

 

 

 

 

of characters.

 

 

 

 

 

 

 

 

 

 

FilterReader

 

 

Abstract base class for streams that support a filtering operation applied on data as

 

 

 

 

 

 

 

characters are read from the stream.

 

 

 

PushbackReader

 

 

Derived class of FilterReader that allows read characters to be pushed back into

 

 

 

 

 

 

 

the stream.

 

 

 

 

 

 

 

 

 

 

BufferedReader

 

 

Adds buffering to the underlying character stream so that there is no need to access

 

 

 

 

 

 

 

the underlying file system for each read and write operation.

LineNumberReader

 

 

Derived class of BufferedReader that keeps track of line numbers as the characters

 

 

 

 

 

 

 

are read from the underlying character stream.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Writer

 

BufferedWriter

PipedWriter

OutputStreamWriter

StringWriter

PrintWriter

 

FilterWriter

FileWriter

Figure 8-3.  Important classes deriving from the Writer class

231

Chapter 8 Java I/O Fundamentals

Table 8-4.  Important Classes Deriving from the Writer Class

 

 

Class name

Short description

StringWriter

A character stream that collects the output in a string buffer, which can be used for

 

creating a string.

OutputStreamWriter

This class is a bridge between character streams and byte streams.

FileWriter

Derived class of InputStreamWriter that provides support for writing character files.

PipedWriter

The PipedReader and PipedWriter classes form a pair for “piped” reading/writing of

 

characters in character stream.

FilterWriter

Abstract base class for streams that supports a filtering operation applied on data as

 

characters when writing them to a character stream.

PrintWriter

Supports formatted printing of characters to the output character stream.

BufferedWriter

Adds buffering to the underlying character stream so that there is no need to access

 

the underlying file system for each read and write operation.

 

 

Reading Text Files

Reader classes read the contents in the stream and try interpreting them as characters, such as a tab, end-of-file, newline, etc. Listing 8-4 implements a simplified version of the type command in Windows. The type command displays the contents of the file(s) passed as command-line arguments.

Listing 8-4.  Type.java

import java.io.FileNotFoundException; import java.io.FileReader;

import java.io.IOException;

//implements a simplified version of "type" command provided in Windows given

//a text file name(s) as argument, it prints the content of the text file(s) on console class Type {

public static void main(String []files) { if(files.length == 0) {

System.err.println("pass the name of the file(s) as argument"); System.exit(−1);

}

// process each file passed as argument for(String file : files) {

// try opening the file with FileReader

try (FileReader inputFile = new FileReader(file)) { int ch = 0;

//while there are characters to fetch, read, and print the

//characters when EOF is reached, read() will return −1,

//terminating the loop

while( (ch = inputFile.read()) != −1) {

//ch is of type int - convert it back to char

//before printing

System.out.print( (char)ch );

}

232

Chapter 8 Java I/O Fundamentals

}catch (FileNotFoundException fnfe) {

//the passed file is not found ...

System.err.printf("Cannot open the given file %s ", file);

}

catch(IOException ioe) {

// some IO error occurred when reading the file ...

System.err.printf("Error when processing file %s... skipping it", file);

}

// try-with-resources will automatically release FileReader object

}

}

}

For a sample text file, here is the output for the type command in Windows and our Type program:

D:\> type SaturnMoons.txt

Saturn has numerous icy moons in its rings. Few large moons of Saturn are - Mimas, Enceladus, Tethys, Dione, Rhea, Titan, Iapetus, and Hyperion.

D:\> java Type SaturnMoons.txt

Saturn has numerous icy moons in its rings. Few large moons of Saturn are - Mimas, Enceladus, Tethys, Dione, Rhea, Titan, Iapetus, and Hyperion.

It works as expected. In this program, you are instantiating the FileReader class and pass the name of the file to be opened. If the file is not found, the FileReader constructor will throw a FileNotFoundException.

Once the file is open, you use the read() method to fetch characters in the underlying file. You are reading character by character. Alternatively, you can use methods such as readLine() to read line by line.

Note that the read() method returns an int instead of a char—it’s because when read() reaches End-Of-File (EOF), it returns −1, which is outside the range of char. So, the read() method returns an int to indicate that the end of file has been reached and that you should stop attempting to read any more characters from the underlying stream.

In this program, you only read a text file; you’ll now try to read from as well as write to a text file.

Reading and Writing Text Files

In the previous example (Listing 8-4) of reading a text file, you created the character stream as follows:

FileReader inputFile = new FileReader(file);

This uses unbuffered I/O, which is less efficient when compared to buffered I/O. In other words, the read characters are directly passed instead of using a temporary (internal) buffer, which would speed up the I/O. To programmatically use buffered I/O, you can pass the FileReader reference to a BufferedReader object, as in the following:

BufferedReader inputFile = new BufferedReader(new FileReader(file);

In the same way, you can also use BufferedWriter for buffered output. (In case of byte streams, you can use BufferedInputStream and BufferedOutputStream, which we’ll discuss later in this chapter).

You’ll now use buffered I/O to read from and write to a text file. Listing 8-5 contains a simplified version of the copy command in Windows.

233

Chapter 8 Java I/O Fundamentals

Listing 8-5.  Copy.java

import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileNotFoundException; import java.io.FileReader;

import java.io.FileWriter; import java.io.IOException;

//implements a simplified version of "copy" command provided in Windows

//syntax: java Copy SrcFile DstFile

//copies ScrFile to DstFile; over-writes the DstFile if it already exits class Copy {

public static void main(String []files) {

if(files.length != 2) {

System.err.println("Incorrect syntax. Correct syntax: Copy SrcFile DstFile"); System.exit(−1);

}

String srcFile = files[0]; String dstFile = files[1];

//try opening the source and destination file

//with FileReader and FileWriter

try (BufferedReader inputFile = new BufferedReader(new FileReader(srcFile)); BufferedWriter outputFile = new BufferedWriter(new FileWriter(dstFile))) {

int ch = 0;

//while there are characters to fetch, read the characters from

//source stream and write them to the destination stream while( (ch = inputFile.read()) != −1) {

//ch is of type int - convert it back to char before

//writing it

outputFile.write( (char)ch );

}

//no need to call flush explicitly for outputFile - the close()

//method will first call flush before closing the outputFile stream

}catch (FileNotFoundException fnfe) {

//the passed file is not found ...

System.err.println("Cannot open the file " + fnfe.getMessage());

}

catch(IOException ioe) {

// some IO error occurred when reading the file ...

System.err.printf("Error when processing file; exiting ... ");

}

// try-with-resources will automatically release FileReader object

}

}

Let’s first check if this program works. Copy this Java source program itself (Copy.java) into another file (DuplicateCopy.java). You can use the fc (file compare) command provided in Windows to make sure that the contents of the original file and the copied file are same, to ensure that the program worked correctly.

234

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]