Java中的InputStream和InputStreamReader有什么区别?

4

我了解到InputStream用于基于字节的读取,每次读取1个字节。而InputStreamReader用于基于字符的读取,因此每次读取一个字符,无需将其首先转换为int再进行读取。

以下是使用InputStream进行读取的示例:

 InputStream input=new FileInputStream("D:/input.txt");

 int c;

 while((c=input.read())!=-1)
 {
    System.out.print((char)c);
 }

这里是使用InputStreamReader进行读取的代码示例:

InputStream input=new FileInputStream("D:/input.txt");

reader=new InputStreamReader(input,"UTF-8");

int c;

while((c=reader.read())!=-1)
{
    System.out.print((char)c);
}

什么是 InputStream InputStreamReader 之间的区别?在这两种情况下,我都必须使用一个 int 来读取数据,在最后如果我想打印该数据,则必须使用“(char)c”进行转换。那么使用 InputStreamReader 的优点是什么?

区别在于 InputStream 本身无法处理大于127的输入值。尝试向测试输入添加一些中文字符,它们将作为两个字节打印出来,而使用 InputStream 版本则是如此。 - markspace
4个回答

10

InputStreamInputStreamReader之间有很大的区别。一个读取字节,而另一个读取字符。根据所使用的编码方式,一个字符可能由多个字节组成。

InputStream.read()中可以了解到:

从输入流中读取下一个字节的数据。

InputStreamReader.read()中可以了解到:

读取单个字符。

InputStreamReader在Java中作为在这两种读取数据方式之间进行桥接的方式:一种将字节流转换为字符流的方法。从它的Javadoc可以了解到:

InputStreamReader是从字节流到字符流的桥梁: 它读取字节并使用指定的字符集将其解码为字符。它使用的字符集可以通过名称指定,也可以显式给出,或者可以接受平台的默认字符集。

每次对InputStreamReader的一个read()方法的调用都可能会导致从基础字节输入流中读取一个或多个字节。为了使字节有效地转换为字符,可能会提前从底层流中读取更多的字节,超过当前读取操作所需的字节数。


谢谢你的回答,但如果是这样的话,为什么两者返回相同的输出呢? 当使用System.out.println(c)显示输出时,我得到了相同的输出。 你能给出任何例子让我可以实际看到区别吗? - user3387084
@user3387084 试着读一篇中文文章吧,你会看到不同之处。 - Tunaki
谢谢 @user3387084,所以基本上应该使用InputStreamReader来处理像“UTF-16”这样的编码,对吗? - user3387084
@user3387084 不,当您想要使用特定编码读取字符时,应该使用InputStreamReader。例如,使用UTF-8,您可以使用Reader一次读取一个中文字符。然而,当您需要明确地读取每个数据字节时,需要使用InputStream - Tunaki
感谢@Tunaki的解释,我之前一直很困惑。现在事情清楚了 :) - user3387084

1

InputStream(输入流)通常总是连接到某些数据源,例如文件、网络连接、管道等。这在Java IO概述文本中也有更详细的解释。

InputStreamReader(输入流读取器)接受一个输入流并将字节流转换为字符流进行读取。例如,一些UTF字符占用2个字节,调用输入流读取器将自动读取这两个字节并将其转换为字符。它用于读取文本流。


0
在InputStreamReader的情况下,您可以使用'char c'代替'int c',而不是'-1'值,您可以使用'null'。像这样:
InputStream input=new FileInputStream("D:/input.txt");

reader=new InputStreamReader(input,"UTF-8");

char c;

while((c=reader.read())!=null)
{
System.out.print(c);
}

因为您正在使用InputStreamReader进行基于字符的读取,所以无需设置数据类型'int',然后再使用'char'进行转换,这是不必要的。 我们需要在InputStream的情况下这样做,因为它是基于字节的读取。


0

有些编码包含跨多个字节的字符。通过使用InputStream进行读取,您会愚蠢地按顺序读取下一个字节,而不是使用InputStreamReader,后者可以根据需要预读以便将下一个字符提供给您,而不是字节。换句话说,假设在流中有0x00 0xA7作为下两个字节。InputStream将在第一次读取时返回0x0,然后在下一个读取时返回0xA7。而采用Unicode编码的InputStreamReader将在第一次读取时返回0x00A7,它代表字符§。

请注意,在大多数情况下最好将InputStreamReader与BufferedReader结合使用。


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