读取多字节字符时InputStream和InputStreamReader之间的区别
InputStream
和InputStreamReader
之间的区别在于InputStream
读取为byte
,而InputStreamReader
读取为char
。 例如,如果文件中的文本是abc
,那么它们都可以正常工作。 但是如果文本是a你们
由a
和两个中文字符组成的a你们
,则InputStream
不起作用。
所以我们应该使用InputStreamReader
,但我的问题是:
InputStreamReader
如何识别字符?
a
是一个字节,但中文字符是两个字节。 它是否读取一个字节并将另一个字符识别为两个字节,或者对于本文中的每个字符, InputStreamReader
是否将其读取为两个字节?
InputStream
读取原始八位位组(8位)数据。 在Java中, byte
类型等同于C中的char
类型。在C中,此类型可用于表示字符数据或二进制数据。 在Java中, char
类型与C wchar_t
类型具有更大的相似性。
然后, InputStreamReader
将数据从某些编码转换为UTF-16。 如果“a你们”在磁盘上编码为UTF-8,则它将是字节序列61 E4 BD A0 E4 BB AC
。 当您使用UTF-8编码将InputStreamReader
传递给InputStreamReader
时,它将被读取为char序列0061 4F60 4EEC
。
Java中的字符编码API包含执行此转换的算法。 您可以在此处找到Oracle JRE支持的编码列表。 如果您想了解这在实践中如何运作的内部, ICU项目是一个很好的起点。
正如Alexander Pogrebnyak所指出的那样 ,你应该几乎总是明确地提供编码。 不指定编码的byte
to- char
方法依赖于JRE默认值 ,这取决于操作系统和用户设置。
您必须通过提供写入二进制文件的字符集给读者提示。例如
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