For most applications, I/O with character streams is no more complicated than I/O with byte streams. Input and output done with stream classes automatically translates to and from the local character set. A program that uses character streams in place of byte streams automatically adapts to the local character set and is ready for internationalization — all without extra effort by the programmer.
If internationalization isn't a priority, you can simply use the character stream classes without paying much attention to character set issues. Later, if internationalization becomes a priority, your program can be adapted without extensive recoding. See the Internationalization trail for more information.
Reader
and
Writer
. As with byte streams, there are character stream classes that
specialize in file I/O:
FileReader
and
FileWriter
.
The
CopyCharacters
example illustrates these classes.
import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class CopyCharacters { public static void main(String[] args) throws IOException { FileReader inputStream = null; FileWriter outputStream = null; try { inputStream = new FileReader("xanadu.txt"); outputStream = new FileWriter("characteroutput.txt"); int c; while ((c = inputStream.read()) != -1) { outputStream.write(c); } } finally { if (inputStream != null) { inputStream.close(); } if (outputStream != null) { outputStream.close(); } } } }
CopyCharacters
is very similar to
CopyBytes
. The most important difference is that
CopyCharacters
uses FileReader
and
FileWriter
for input and output in place of
FileInputStream
and FileOutputStream
.
Notice that both CopyBytes
and CopyCharacters
use an int
variable to read to and write from. However, in
CopyCharacters
, the int
variable holds a
character value in its last 16 bits; in CopyBytes
, the
int
variable holds a byte
value in its last
8 bits.
FileReader
, for example, uses
FileInputStream
, while
FileWriter
uses FileOutputStream
.
There are two general-purpose byte-to-character "bridge" streams:
InputStreamReader
and
OutputStreamWriter
. Use them to create character streams when there are no prepackaged
character stream classes that meet your needs. The
sockets lesson
in the
networking trail
shows how to create character streams from the byte streams provided
by socket classes.
"\r\n"
), a single
carriage-return ("\r"
), or a single line-feed
("\n"
). Supporting all possible line terminators allows
programs to read text files created on any of the widely used
operating systems.
Let's modify the CopyCharacters
example to use
line-oriented I/O. To do this, we have to use two classes we haven't
seen before,
BufferedReader
and
PrintWriter
.
We'll explore these classes in greater depth in Buffered I/O and Formatting. Right now, we're just
interested in their support for line-oriented I/O.
The
CopyLines
example invokes BufferedReader.readLine
and
PrintWriter.println
to do input and output one line at a
time.
import java.io.FileReader; import java.io.FileWriter; import java.io.BufferedReader; import java.io.PrintWriter; import java.io.IOException; public class CopyLines { public static void main(String[] args) throws IOException { BufferedReader inputStream = null; PrintWriter outputStream = null; try { inputStream = new BufferedReader(new FileReader("xanadu.txt")); outputStream = new PrintWriter(new FileWriter("characteroutput.txt")); String l; while ((l = inputStream.readLine()) != null) { outputStream.println(l); } } finally { if (inputStream != null) { inputStream.close(); } if (outputStream != null) { outputStream.close(); } } } }
readLine
returns a line of text with the line.
CopyLines
outputs each line using println
,
which appends the line terminator for the current operating system.
This might not be the same line terminator that was used in the input
file.
There are many ways to structure text input and output beyond characters and lines. For more information, see Scanning and Formatting.