2011-06-30 35 views
5

我想从二进制流中读取数据,其中的一部分应该被解析为UTF-8。从InputStream中读取文本和二进制数据

InputStream直接用于二进制数据,而对其UTF-8文本使用InputStreamReader不起作用,因为即使读取最大值时阅读器也会预读并弄乱后续二进制数据n个字符。

我认识到这个问题与Read from InputStream in multiple formats非常相似,但是提出的解决方案特定于HTTP流,这对我没有帮助。

我以为只是把所有东西都看成是二进制数据,然后把相关的部分转换成文本。但是我只有字符数据的长度信息,而不是字节。因此,我需要从流中读取字符的东西来了解编码。

有没有办法告诉InputStreamReader不要读取超过读取给定数量的字符所需的更多?还是有一个阅读器支持二进制数据和文本编码,并可以在这些模式之间切换?

回答

2

您需要先阅读二进制部分。如果您认识到需要UTF-8解码的字节部分,则需要提取这些字节并对其进行解码。

​​
+1

问题是,对于UTF8,字节数可能与字符数不同。所以我需要找出字符串中多字节字符的数量,读取更多字节并再次进行转换,并一遍又一遍地进行处理,直到数字匹配。 – tajmahal

+0

我会说你的格式不是很容易解码,如果可以,我会解决它。但是如果你知道字符数,你可以自己解析UTF-8。 (但发送实际数字字节会简单得多) –

+0

另一种方法是读取比需要更多的数据。以预期的字符数量为例substring()并转换为UTF-8来确定长度。使用mark()和reset()并读取你现在知道的长度。 (这只有在UTF-8编码完全相同时才有效:|例如,nul字节\ 0以两种不同的方式编码。(其他字符也可以) –

2

我认为你只是不应该使用StreamReader。读者处理文本,但你一起处理文本和二进制数据。

没有办法。您必须阅读二进制缓冲区并自行解释您的格式,即查找文本提取字节的位置并将它们转换为字符串。

为了简化这个任务,我建议你创建你自己的类(比如ProtocolRecord)。它应该是可序列化的。它将包含你所有的领域。 现在你有2个选项:

(1)简单的一个 - 使用java序列化机制。在这种情况下,您只需将DataInputStream用于读取并将DataOutputStream用于写入,然后读取/写入对象即可。这种方法的缺点是你无法控制你的协议。 (2)自己实现方法readObject()和writeObject()。现在使用上面解释的DataInputStream和DataOutputStream。 在这种情况下,你必须实现序列化协议,但至少它被封装到你的类中。

它认为DataInputStream是你所需要的。