Java平台约定使用Unicode存储字符值。字符流(Character stream)I / O自动将此内部格式与本地字符集转换。在西方语言环境中,本地字符集通常是ASCII的8位超集。
对于大多数应用程序,使用字符流的I / O并不比使用字节流的I / O复杂。使用流类完成的输入和输出会自动与本地字符集进行转换。使用字符流代替字节流的程序会自动适应本地字符集,并可以进行国际化,而这一切都无需程序员付出额外的精力。
如果国际化不是优先事项,则可以简单地使用字符流类,而不必过多关注字符集问题。以后,如果国际化成为当务之急,则可以在不进行大量重新编码的情况下修改您的程序。有关更多信息,请参见 国际化。
使用字符流
所有字符流类均源于 Reader和 Writer。与字节流一样,有些字符流类专门研究文件I / O: FileReader和 FileWriter。CopyCharacters示例说明了这些类。
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与CopyBytes非常相似。最重要的区别在于,CopyCharacters使用FileReader和FileWriter代替了FileInputStream和FileOutputStream用于输入和输出。注意,CopyBytes和CopyCharacters都使用int变量进行读写。但是,在CopyCharacters中,int变量的后16位保留一个字符值;在CopyBytes中,int变量在其后8位中保存一个byte值。
使用字节流的字符流
字符流通常是字节流的“包装器”。字符流使用字节流执行物理I / O,而字符流则处理字符和字节之间的转换。例如,FileReader使用FileInputStream,而FileWriter使用FileOutputStream。
有两个通用的字节到字符“桥接”流: InputStreamReader和 OutputStreamWriter。当没有预打包的字符流类可以满足您的需求时,使用它们来创建字符流。自定义网络中的读写套接字课程显示了如何从套接字类提供的字节流中创建字符流。
面向行的I / O
字符I / O通常以比单个字符大的单位出现。一个常见的单位是行:一串字符,末尾有一个行终止符。换行符可以是回车/换行序列("\r\n"),单个回车("\r")或单个换行("\n")。支持所有可能的行终止符,使程序可以读取在任何广泛使用的操作系统上创建的文本文件。
让我们修改CopyCharacters示例以使用面向行的I / O。要做到这一点,我们必须使用我们以前从未见过的两个类, BufferedReader和 PrintWriter。我们将在缓冲流和格式化中更深入地探讨这些类。现在,我们只是对他们对基于行的I / O的支持感兴趣。CopyLines示例一次调用BufferedReader.readLine和PrintWriter.println执行输入和输出一行。
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将返回一行文本。CopyLines使用println输出每行,该行将当前操作系统的行终止符附加到后面。这可能与输入文件中使用的行终止符不同。
除了字符和行以外,还有许多种方法来构造文本输入和输出。有关更多信息,请参见扫描和格式化。
