关于 Java 的 I/O 类 的问题

Questions on Java's I/O Classes

我正在阅读 java 中有关网络的教程 (client/server),我有一个我不明白的问题。

https://docs.oracle.com/javase/tutorial/networking/sockets/readingWriting.html

我经常看到这个

BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

BufferedReader inputStream = new BufferedReader(new FileReader("xanadu.txt"));
PrintWriter outputStream = new PrintWriter(new FileWriter("characteroutput.txt"));

我知道 BufferReader 的构造函数是

BufferedReader(Reader in)

1) 我还知道,由于 InputStreamReader 是由 Reader class 继承的,因此您可以通过 BufferedReader 构造函数传递它。但我的问题是为什么我们需要 InputStreamReader?是因为 InputStreamReader 可以容纳一个输入流(根据它在 API 中的构造函数)

编辑:我有误,请忽略

2) 现在对于下一部分,inputStream & outputStream(根据API)是从Object class继承的。这两个 classes 如何分别分配为 BufferedReader 和 PrintWriter。这是因为它们都被对象class继承了,还是另有原因?因为如果是这样的话,怎么会有人知道你可以分配什么 class 就好像一切都应该由对象 class 继承一样。

3) 最后但同样重要的是,这里还有一个关于 BufferedReader 和 PrintWriter 的问题

BufferedReader inputStream = new BufferedReader(new FileReader("xanadu.txt"));
PrintWriter outputStream = new PrintWriter(new FileWriter("characteroutput.txt"));

为什么这两个 classes 选择通过 FileReader 和 FileWriter classes 的引用?

我想我想了解更多关于为什么选择这些特定 classes 的信息。

提前致谢!

1) 要构造BufferedReader,您需要一个Reader参数。 System.in 不是 Reader。 Java IO 拼图的每个部分只做一件事:InputStreamReaderInputStream 得到一个 Reader,然后 BufferedReader 缓冲 ​​Reader .

2) 他们不能,正是因为#1。首先将 InputStream 包装在 ReaderWriter 包装器中,然后您可以做其他事情。

3) 因为他们正在读取/写入文件,而不是流。 (编辑:并且,正如评论中提到的 pvg,inputStream = new BufferedReader(...)outputStream = new PrintWriter(...) 是极其混乱的变量名称。)


基本上,它就像一个制造。你有 System.in,这是一个 InputStream。这意味着他给你的是纯字节。您不需要纯字节;您希望获得字符(即由某些字符编码解析的字节,例如 UTF-8)。但是 InputStream 不知道该怎么做。

输入InputStreamReader。作为每个Reader,他知道如何给你角色。具体来说 InputStreamReader 知道如何从 InputStream 中获取字节并将其作为字符传递。所以你把他排在System.in前面,这样你就不用对付他了。

但您不想一次获取每个字符。你想要更多。您希望能够一次阅读整行!你想要……缓冲!输入 BufferedReader:他是站在另一个 Reader 前面的人,收集每个角色并把它扔掉,直到你要一些。

要了解到底发生了什么,您需要了解基于字节的 IO 和基于文本的 IO 之间的关键区别,并研究每个 class' 的构造函数以了解它究竟是什么样的东西包装(尽管名称是一个很好的提示)。

好的,原因很简单

这是装饰器设计模式。 你拿一个基本的 object 并继续在它上面添加所需的装饰。 示例:有 2 种浇头的披萨(我现在很饿)

你这样做是因为它减少了所需的不同 classes 的数量(InputStreamReader * Buffered/UnBuffered * bla bla bla 导致许多不同的组合,所以如果我们有一个 child class 对于每个组合,它将是 100+ stream classes 我们会感到困惑,所以我们简单地装饰它(所有类型都有相同的接口,我们在构造函数中相互传递)

如果仍有疑问,请 google 装饰器模式了解详情