Io DataInputStream.skipBytes(n)何时可以不跳过n个字节?
声明它“试图从输入流中跳过n个字节的数据,丢弃跳过的字节。但是,它可能会跳过一些较小的字节数,可能为零。这可能是由多种情况造成的;在跳过n个字节之前到达文件末尾只是一种可能性。”Io DataInputStream.skipBytes(n)何时可以不跳过n个字节?,io,java,Io,Java,声明它“试图从输入流中跳过n个字节的数据,丢弃跳过的字节。但是,它可能会跳过一些较小的字节数,可能为零。这可能是由多种情况造成的;在跳过n个字节之前到达文件末尾只是一种可能性。” 除了到达文件末尾,为什么skipBytes()不能跳过正确的字节数?(我正在使用的DataInputStream将包装FileInputStream或PipedInputStream) 如果我确实想跳过n个字节并抛出一个EOFEException,如果这导致我转到文件的末尾,我是否应该使用readFully()并忽略生
skipBytes()
不能跳过正确的字节数?(我正在使用的DataInputStream
将包装FileInputStream
或PipedInputStream
)EOFEException
,如果这导致我转到文件的末尾,我是否应该使用readFully()
并忽略生成的字节数组?还是有更好的办法2) readFully()(它将始终等待足够的输入,否则将失败)或在循环中调用skipBytes()。我认为前者可能更好,除非阵列真的很大。Josh Bloch最近公布了这一点。这是一致的,因为InputStream.read不能保证读取尽可能多的字节。然而,作为API方法,它是完全没有意义的。InputStream可能也有Readfull。事实证明Readfull()增加的性能开销比我愿意忍受的还要多
最后我妥协了:我调用skipBytes()一次,如果返回的字节数少于正确的字节数,我就为剩余的字节调用readFully()。它读取的是虚拟机上的网络连接,所以我想这可能有很多原因。我通过简单地强制输入流跳过字节数,直到它跳过了我想要的字节数:
int byteOffsetX = someNumber; //n bytes to skip
int nSkipped = 0;
nSkipped = in.skipBytes(byteOffsetX);
while (nSkipped < byteOffsetX) {
nSkipped = nSkipped + in.skipBytes(byteOffsetX - nSkipped);
}
int byteOffsetX=someNumber//n个要跳过的字节
int nSkipped=0;
nSkipped=in.skipBytes(字节偏移量);
while(nSkipped
根据文档,readFully()
是既有效又保证有效的唯一方法
实际的Oracle实现是。。。令人困惑的:
public final int skipBytes(int n) throws IOException {
int total = 0;
int cur = 0;
while ((total<n) && ((cur = (int) in.skip(n-total)) > 0)) {
total += cur;
}
return total;
}
public final int skipBytes(int n)抛出IOException{
int-total=0;
int cur=0;
而(共0个){
总+=cur;
}
返回总数;
}
当skipBytes()
与skip()
具有基本相同的契约时,为什么要在循环中调用skip()
?如果以下两个条件都成立,那么以这种方式实现它将非常有意义:skipBytes()
保证只在EOF上跳过比请求少的字节,并且skip()
保证在可能的情况下至少跳过一个字节(就像read()
那样)
更糟糕的是,skip()。它只是没有承诺做到这一点,这意味着其他实现可能无法做到这一点(如果在将来的版本中进行更改,即使是Oracle one也可能在将来失败)
为了完全安全:调用readBytes()
,如果它不起作用,则分配一个临时缓冲区,并调用readFully()
(如果需要跳过任意大量数据,请在此使用循环)
另一方面,在循环中调用skipBytes()
是毫无意义的。至少在Oracle实现中是这样,因为它已经是一个循环。实际上,在循环中调用skipBytes()
并不能完成这项工作,因为无法正确终止循环:skipBytes()
可能返回0,但它没有任何意义(与read()
不同,后者会根据原因返回-1或0)。更令人沮丧的是,在Oracle实现中,skipBytes()
实际上在一个循环中调用skip()
,尽管两者基本上具有相同的契约。谈论糟糕的API设计。。。