输入流跳过字节
这是我第二次遇到输入流这个极其烦人的问题。 这个InputStream属于一个应该接收图像的Socket。读取该图像的代码如下:
InputStream input = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(input);
BufferedReader bufferedReader = new BufferedReader(reader);
int total = Integer.parseInt(bufferedReader.readLine());
int bytesRead = 0;
byte[] buffer = new byte[total]; // total is the total size of the image
while (bytesRead < total) {
int next = input.read(buffer, bytesRead, total-bytesRead);
if (next > 0) {
bytesRead += next;
System.out.println("Read: " + bytesRead);
}
}
现在奇怪的是,该代码跳过图像的前 1182 个字节,然后读取剩余部分。因此,当total
大小为15000字节时,它读取字节1182-15000。
我检查了Wireshark,整个图像都被传输了。代码没有抛出任何异常。 input.read()
照常返回 -1。
先前的数据已使用 BufferedReader 从流中读取。该数据只有 5 个字符长,因此它不能包含丢失的 1K,但我的猜测是 BufferedReader.readLine() 方法从 InputStream 读取(缓冲)的字节数超出了所需的字节数。这可能是正确的吗?
几个月前我遇到了同样的问题,但我完全不知道如何解决它。
希望任何人都可以提供帮助。
提前致谢。
编辑:我可以通过在发送图像大小和图像数据之间添加 100 毫秒的睡眠来解决该问题。它解决了问题,但我仍然很想知道更合适的解决方案
For the second time I have this extremely anoying problem with an InputStream.
This InputStream belongs to a Socket that is supposed to receive an image. The code for reading this image is as below:
InputStream input = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(input);
BufferedReader bufferedReader = new BufferedReader(reader);
int total = Integer.parseInt(bufferedReader.readLine());
int bytesRead = 0;
byte[] buffer = new byte[total]; // total is the total size of the image
while (bytesRead < total) {
int next = input.read(buffer, bytesRead, total-bytesRead);
if (next > 0) {
bytesRead += next;
System.out.println("Read: " + bytesRead);
}
}
Now the strange thing is that this code skips the first 1182 bytes of the image, and then reads the remaining part. So when the total
size is 15000 bytes, it reads byte 1182-15000.
I checked Wireshark and the whole image is transmitted. The code throws no exceptions. input.read()
returns -1 as usual.
Pervious data has been readed from the stream using a BufferedReader
. This data is only 5 characters long so it can't contain the missing 1K, but my guess is that the BufferedReader.readLine() method reads (buffers) more bytes from the InputStream than needed. Could this be correct?
I've had the same problem a few months ago but I absolutely have no clue on how I solved it.
Hope anyone can help.
Thanks in advance.
EDIT: I can solve the problem by adding a 100 ms sleep between sending the image size and the image data. It solves the problem but I would still realy like to know a more appropriate solution
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我的猜测是 BufferedReader 会假设您之后执行的任何读取操作都会经过它,因此它会很乐意以缓冲区大小的增量消耗输入。
您可以做的一件事是在
input
之上使用BufferedInputStream
,在其之上实例化DataInputStream
来执行readLine( )
,然后在循环中使用BufferedInputStream
。该文档说readLine
已被弃用,因为它不能正确地将字节转换为字符,但我希望您的第一行仅包含十进制数字,它不应该遇到这个问题。我写了一个简短的测试,希望它能涵盖您的用例:
My guess is the
BufferedReader
will assume that whatever reading operations you're performing afterwards will go through it, so it will happily consume input in increments of its buffer size.One thing you could do is use a
BufferedInputStream
on top ofinput
, instantiate aDataInputStream
on top of that to do thereadLine()
, and then use theBufferedInputStream
in your loop. The documentation saysreadLine
is deprecated because it doesn't convert bytes to characters properly, but I'm hoping that with your first line containing only decimal digits, it shouldn't run into that problem.I've written a short test, I hope it covers your use case:
您是否考虑过仅发送图像数据(没有前面的图像大小)并使用外部库,例如 Apache Commons IO< /a> 为您处理这个问题?特别是,我认为您会发现 IOUtils.toByteArray(InputStream input) 有趣,例如
Have you considered just sending the image data (without the preceding image size) and using an external library such as Apache Commons IO to handle this for you? In particular, I think that you will find IOUtils.toByteArray(InputStream input) interesting, e.g.
正如名称
**Buffererd**Reader
所示,它将从底层读取器以及流中获取比第一行更多的字节。否则就不会被称为“缓冲”。不幸的是,我不知道 Java 中有任何未弃用的类允许以您想要的方式混合二进制和文本数据。
我建议您修改协议并以某种二进制编码传输图像的长度。然后你可以坚持使用
InputStream
。As the name
**Buffererd**Reader
indicates it will snarf more bytes than just the first line from the underlying reader and hence also from the stream. Otherwise if would not be called "buffered".Unfortunately I'm not aware of any non-deprecated class in Java which allows mixing of binary and textual data in the way you want.
I suggest, that you modify your protocol and transfer the length of the image also in some binary encoding. Then you can stick to
InputStream
.