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

InputStreamInputStreamReader之间的区别在于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