使用一个输入流作为多个更高级别的输入流(如缓冲读取器、DataInputStream)的源



我只是在徘徊,这是一个好主意还是坏主意:

InputStreamReader in = new InputStreamReader(socket.getInputStream());
BufferedReader reader = new BufferedReader(in);
DataInputStream dis = new DataInputStream(in);

现在我想从缓冲阅读器中读取。如果某个命令(只是一个字符串(到达,我想继续从 DataInputStream 读取。

这行得通吗?如果是,这被认为是好的做法还是坏做法?

(我认为你的例子在什么是读者和什么是输入流方面是破碎的,但我还是得到了这个问题(

您可以执行类似操作,但您需要确切地知道每个组件在缓冲方面的行为。

您正在使用的套接字输入流仅允许您读取某个字节一次(结帐InputStream.markSupported()(。您可以将该输入流包装在BufferedInputStream中,该可以有效地读取前面的一些字节,但也添加了执行mark()reset()的功能。

这意味着BufferedInputStream顶部的任何读取器/输入流都可以提前读取、标记、向后跳等。但是在这里您需要小心,以免添加另一层"缓冲区" - 即BufferedReader> InputStreamReader> BufferedInputStream> InputStream.

所以答案是肯定的,它可以工作,只要知道每个组件的确切行为(我经常看到人们为了它而扔BufferedXXX(。

在你的例子中,我会做:

BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
InputStreamReader reader = new InputStreamReader(in, "utf-8"); // consider char encoding
DataInputStream dis = new DataInputStream(in);

这是行不通的。

缓冲读取器读取缓冲区并将其分析为行。因此,例如,如果有 2 行半可用,它可能会将有效载荷流的标记移动到该位置。现在您读取行,然后决定使用 DataInputStream 读取长整型值。代码将尝试从有效负载流的位置(2.5 行之后(读取此值。但是你真的想读第一行后面的数字。

我认为这个例子也解释了为什么这个想法不是一个好的做法。Java 流实现装饰器(包装器(模式。每个流都添加自己的功能。尝试用多个包装器包装相同的"真实"流看起来像是试图打破这种封装。

最新更新