Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
Java 平台使用 Unicode 规范存储字符值。字符流 I/O 自动将此内部格式转换为本地字符集。在西方的语言环境中,本地字符集通常是 ASCII 的 8 位超集。
对于大多数应用程序,具有字符流的 I/O 并不比具有字节流的 I/O 复杂。使用流类完成的输入和输出会自动转换为本地字符集和从本地字符集转换。使用字符流代替字节流的程序会自动适应本地字符集并准备好进行国际化 一切都没有程序员的额外努力。
如果国际化不是优先考虑事项,你可以简单地使用字符流类而不必过多关注字符集问题。之后,如果国际化成为优先事项,你的程序可以进行调整而无需进行大量重新编码。有关详细信息,请参阅 Internationalization 路径。
所有字符流类都继承自 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
。当没有符合你需求的预打包字符流类时,使用它们来创建字符流。networking trail 中的 sockets lesson 显示了如何从套接字类提供的字节流创建字符流。
字符 I/O 通常以比单个字符更大的单位出现。一个常见的单位是行:即一串字符,末尾有一个行终止符。行终止符可以是回车/换行序列("\r\n"
),单个回车符("\r"
),或者单个换行("\n"
)。支持所有可能的行终止符允许程序读取在任何广泛使用的操作系统上创建的文本文件。
让我们修改 CopyCharacters
示例以使用面向行的 I/O. 为此,我们必须使用前面没有见过的两个类,BufferedReader
和 PrintWriter
。我们将在 Buffered I/O 和 Formatting 中更深入地探索这些类。现在,我们只对他们对面向行的 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
输出每一行,该行附加当前操作系统的行终止符。这可能与输入文件中使用的行终止符不同。
有许多方法可以构建超出字符和行的文本输入和输出。有关更多信息,请参阅 Scanning and Formatting。