1.InputStreamReader

流的另一个有趣的特性是您可以将多个流组合成。一个流不仅可以从它的内部数据源中读取数据,还可以从另一个流中读取数据。

这是 Java 中一种非常强大的机制,它可以通过将一个流连接到另一个流来创建复杂的数据读取场景。这样的方案看起来像这样:

InputStreamReader 类

当程序从数据流中读取数据时,数据流又从其数据源(例如另一个数据流或文件)中读取数据。

更重要的是,每个数据流不仅可以读入和发出数据,还可以对其进行转换或对其进行各种操作。这种“中间流”的一个很好的例子就是类InputStreamReader

我们已经知道一个名为的类FileReader——它是一个Reader从文件中读取数据的类。从哪里InputStreamReader获取数据?没错——来自InputStream.

当你创建一个InputStreamReader对象时,你需要传入一个InputStream对象或者它的一个子类。例子:

String src = "c:\\projects\\log.txt";
FileInputStream input = new FileInputStream(src);
InputStreamReader reader = new InputStreamReader(input);

该类InputStreamReader具有该类所具有的所有方法Reader,并且它们以完全相同的方式工作。

InputStreamReader类和类之间的主要区别FileReader在于它们从何处读取数据。FileReader从文件中读取数据(呃——这就是它被称为 的原因FileReader),InputStreamReader但从InputStream.

FileReader当您使用该方法从对象中读取一个字符时read(),它会依次从磁盘上的文件中读取两个字节并将它们作为chars.

InputStreamReader当您使用该方法从对象中读取一个字符时read(),它会依次从FileInputStream传递给它的对象中读取两个字节,然后再从文件中读取数据。结果是对方法的调用链read()


2.BufferedReader

您可能会经常使用的另一个有趣的类是BufferedReader. 这也是从另一个流读取数据的“中间流”。

顾名思义,该类BufferedReader是 的子类Reader可让您阅读 characters。但最有趣的是,您还需要以流的形式向它传递一个数据源,可以从中读取字符,即继承该类的流Reader

重点是什么?与 不同InputStreamReader,该类BufferedReader不会将字节转换为字符:它根本不会转换任何内容。相反,它缓冲数据

当程序从BufferedReader对象中读取单个字符时,该对象会同时从其源流中读取大量字符。并将它们存储在内部。

当从对象中读取下一个字符时BufferedReader,它只是从其内部缓冲区数组中获取下一个字符并返回它,而无需访问数据源。只有当缓冲区中的所有字符都用完时,它才会读入另一个大字符数组。

该类BufferedReader还有一个非常有用的方法 — String readLine(),它可以让您一次从源流中读取整个数据字符串。例如,您可以使用此方法读取文件并将其内容逐行显示在屏幕上。例子:

我们专门写了一些紧凑的代码来说明这有多方便。这段代码也可以写得更详细一点。

String src = "c:\\projects\\log.txt";

try(FileReader in = new FileReader(src);
BufferedReader reader = new BufferedReader(in))
{
   while (reader.ready())
   {
      String line = reader.readLine();
      System.out.println(line);
   }
}
创建一个FileReader对象。数据源是一个文件。
创建一个BufferedReader对象。数据源是一个FileReader.
只要阅读器中还有数据
读取一行
显示该行
重要的一点:

如果将多个流链接在一起,则只close()需要在其中一个上调用该方法。该流将在其数据源上调用该方法,依此类推,直到close()在最终数据流上被调用。



3.从控制台读取

还有一个更有趣的事实:该类Scanner只不过是一个从 中读取数据的中间输入流System.in,它也是一个数据流。

以下是从控制台读取一行的两种方法:

扫描仪类 BufferedReader 和 BufferedWriter 类
InputStream stream = System.in;
Scanner console = new Scanner(stream);
String line = console.nextLine();
InputStream stream = System.in;
InputStreamReader reader = new InputStreamReader(stream);
BufferedReader buff = new BufferedReader(reader);
String line = buff.readLine();

我们的朋友只不过是类的静态变量。这是一个名字是。System.ininSystemInputStreamin

因此,几乎从您在 CodeGym 上学习 Java 的一开始,您就一直在处理数据流并从中构建链。但现在你会更有意识地去做。