读取多字节字符时,InputStream和InputStreamReader之间的区别

31
InputStreamInputStreamReader的区别在于,InputStream按字节(byte)读取,而InputStreamReader按字符(char)读取。例如,如果文件中的文本是abc,则两者都可以正常工作。但如果文本是由一个a和两个汉字组成的a你们,则InputStream无法正常工作。

因此我们应该使用InputStreamReader,但我的问题是:

InputStreamReader如何识别字符?

a是一个字节,但一个汉字是两个字节。它是否将a读取为一个字节,并将其他字符识别为两个字节,还是对于文本中的每个字符,InputStreamReader都将其读取为两个字节?

2个回答

30

InputStream 是用来读取原始的八位字节数据。在Java中,byte类型等同于C语言中的char类型。在C语言中,该类型可用于表示字符数据或二进制数据。在Java中,char类型与C语言中的wchar_t类型更为相似。

InputStreamReader 会将数据从某种编码转换为UTF-16。如果 "a你们" 在磁盘上以UTF-8编码,则其字节序列为 61 E4 BD A0 E4 BB AC。当您将InputStream传递给InputStreamReader并使用UTF-8编码时,它将被读取为字符序列 0061 4F60 4EEC

Java中的字符编码API包含执行此转换所需的算法。您可以在Oracle JRE的此处找到受支持的编码列表。如果要了解实际工作原理的内部细节,ICU项目是一个很好的起点。

正如Alexander Pogrebnyak在这里所指出的,您几乎总是应该明确提供编码方式。没有指定编码的byte-to-char方法依赖于JRE默认设置,这取决于操作系统和用户设置。


10
您需要为读取器提供一个字符集,以表明您的二进制文件是使用哪种字符集编写的。例如:
Reader reader =
   new InputStreamReader(
       new FileInputStream( "/path/to/file" ),
       "UTF-8" // most likely that the encoding of the file
   )

如果不提供提示,它将使用您平台的默认编码方式,而在许多情况下,这并不是您想要的。

此链接有一个关于编码的好解释:http://www.joelonsoftware.com/articles/Unicode.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接