2012-07-10 19 views
-1

我BufferedInputStream.read(字节[])的理解是,读操作从POS开始,并读取直到字节数组已满或发生流的末尾。不一致的BufferedInputStream读取(字节[])行为

我呼吁在下面的BufferedInputStream readInt方法。

public class XDRInputStream { 

private InputStream stream; 

private byte[] buffer4 = new byte[4]; // fixed size buffers 
private byte[] buffer8 = new byte[8]; 

public XDRInputStream(InputStream stream) { 
    this.stream = stream; 
} 

public InputStream getInternalStream() { 
    return stream; 
} 

public int readInt() throws IOException { 
    if (stream.read(buffer4) != -1) { 
     return ((buffer4[0] & 0xFF) << 24) 
      | ((buffer4[1] & 0xFF) << 16) 
      | ((buffer4[2] & 0xFF) << 8) 
      | ((buffer4[3] & 0xFF)); 
    } else { 
     throw new EOFException("End of stream"); 
    } 
} 

当我在Eclipse调试器跟踪执行时,stream.read(buffer4)呼叫 - 无论起始POS值的 - 通常会导致POS被设置为4的值,和4个字节读来自前四个字节输入流。 read(byte [])调用是否在某些情况下静默地重置流,如果是,何时?这似乎是有意的行为(这不是我的代码),当它以这种方式运行时,程序运行良好。

我遇到的问题是,有时候,只有在Windows上,并且只有当输入流包含特定内容时(在这种情况下,由于丢弃的套接字导致的错误消息),pos的重置不会发生似乎意图是,这会导致方法从流中的错误位置读取并返回不正确的值。

我们在Solaris上使用相同的代码,虽然我没有做过这个平台上调试器步进式,在Solaris下的程序工作正常,我试图的bug修复不会发生。对于我不知道的流,是否会出现一些特定于平台的问题?

谢谢。

+0

您是否在到达“理解”之前阅读Javadoc? – EJP 2012-07-10 09:58:08

回答

2

作为一个经验法则,你不能依靠整个阵列上被从流一次性读取。 如果你看看docs,你会看到返回的read(byte[])是读取的字节数,可能是整个数组长度或更少。如果还没有数据,甚至为0。这是非常典型的(也可能取决于操作系统)读取少于整个阵列。

所以,你必须确保你实际读取4个字节。

+0

你说得对,当然这是对代码的改进,但我不认为这是我眼前的问题的原因。只要查看流缓冲区内容,我就可以知道数据在那里,并且如预期的那样从缓冲区中确实读取了4个字节 - 只是从意外的起点开始。 – gjr 2012-07-10 06:06:02

+0

找出问题所在 - 如果pos等于缓冲区中的最后一个字节,则read(bytes [])将假定缓冲区已被完全读取,并调用fill()以新东西覆盖内容。解决这个问题将不得不在我的上游代码中实现。 – gjr 2012-07-10 08:06:38

+0

@glr'pos'可以位于缓冲区的末尾的唯一方法是* *已被完全读取或跳过。没有“假设”。 – EJP 2014-10-20 21:20:45

1

我对BufferedInputStream.read(byte [])的理解是,读操作从pos开始,一直读取,直到字节数组已满或数据流结束。

你的理解是不正确。你的理解与Javadoc完全相反,它说,如果有必要,它会阻塞,直到至少有一个字节可用,读取任何可用的内容,并返回读取的字节数,如果EOS是-1,则返回-1改为阅读。

相关问题