java.io.InputStream及其子类型中数据的健壮跳过
我正在处理一个二进制流,需要高效地跳过一系列我不感兴趣的数据,跳转到一些将要处理的数据java.io.InputStream及其子类型中数据的健壮跳过,java,stream,inputstream,java-io,skip,Java,Stream,Inputstream,Java Io,Skip,我正在处理一个二进制流,需要高效地跳过一系列我不感兴趣的数据,跳转到一些将要处理的数据 InputStream.skip(long)在保证方面没有多大作用: 跳过并丢弃此输入流中的n字节数据。由于各种原因,skip方法可能会跳过一些较小的字节数,可能是0。这可能由多种情况中的任何一种导致;在跳过n个字节之前到达文件末尾只是一种可能性。返回跳过的实际字节数 我需要知道发生了两件事中的一件: 溪流结束了 字节被跳过 很简单。然而,本描述中提供的宽大性意味着,例如,BufferedInputStrea
InputStream.skip(long)
在保证方面没有多大作用:
跳过并丢弃此输入流中的n字节数据。由于各种原因,skip方法可能会跳过一些较小的字节数,可能是0。这可能由多种情况中的任何一种导致;在跳过n个字节之前到达文件末尾只是一种可能性。返回跳过的实际字节数
我需要知道发生了两件事中的一件:
BufferedInputStream
可以跳过几个字节并返回。当然,它告诉我,它只是跳过了这几个,但不清楚为什么
因此,我的问题是:您是否可以使用
InputStream.skip(long)
,以便您知道流何时结束或跳过何时成功完成?这似乎适用于跳过n
字节:
long skippedTotal = 0;
while (skippedTotal != n) {
long skipped = _stream.skip(n - skippedTotal);
assert(skipped >= 0);
skippedTotal += skipped;
if (skipped == 0)
break;
}
boolean skippedEnough = skippedTotal == n;
但是,不清楚它是否适用于可以传递到我的库的
InputStream
的所有实现。我想知道是否应该实现我自己的缓冲跳过方法。我认为我们无法获得真正健壮的实现,因为skip()
方法契约非常奇怪。一方面,EOF
的行为没有得到很好的定义。如果我想跳过8个字节,并且是.skip(8)
返回0
,那么决定是否重试并不容易,如果某些实现选择在EOF
处返回0
,则存在无限循环的危险。而且available()
也不可信
因此,我提议如下:
/**
* Skips n bytes. Best effort.
*/
public static void myskip(InputStream is, long n) throws IOException {
while(n > 0) {
long n1 = is.skip(n);
if( n1 > 0 ) {
n -= n1;
} else if( n1 == 0 ) { // should we retry? lets read one byte
if( is.read() == -1) // EOF
break;
else
n--;
} else // negative? this should never happen but...
throw new IOException("skip() returned a negative value. This should never happen");
}
}
我们不应该返回一个值来通知“真正跳过”的字节数吗?还是一个布尔值来通知已达到EOF?我们不能以稳健的方式做到这一点。例如,如果我们调用对象的
skip(8)
,即使我们处于EOF
,或者文件只有2个字节。但是,从某种意义上说,该方法是健壮的,它做了我们想要做的事情:跳过n
字节(如果可能的话),让我继续处理它(如果我下一次读取返回-1
,我将知道EOF
已达到)。我对此问题晚了6年
原则上,跳过(int n)之间没有区别
和readFully(int n)。在这种情况下,你不感兴趣
在字节中
对于实时流,即tcp套接字或
附加到,skip(n)可以阻止(等待)它
«跳过»0字节,具体取决于用户等待的首选项
返回EOF或-1表示任务结束
流,并应将其返回给最终用户
因为在这一点之后不会有其他事情发生
为了有效地跳过文件中的字节,我需要
探索随机io、通道。但这种优化是不可能的
在任何输入流中都是通用的。我不认为任何
InputStream
实现都会偏离约定,即返回实际跳过的字节数。@EJP,我同意。我关心的是,是否由于某种IO伪影(缓冲等)或流结束而跳过了较少的字节。如果流尚未结束,skip
仍可能返回零。在什么情况下,您知道跳过不起作用是因为没有更多的字节,而不是它在网络上等待字节?我看到的问题是,我们无法确定在skipped==0
时不应该重试。此外,布尔值skippedOutgh
不可信。看我的回答。你的回答具体地详述了我所关心的事情。我发布的代码在实践中似乎有效,但我不确定它是否适用于InputStream
的所有实现。您的扩展看起来很有趣,我将很快在中试用。目前,我的API尝试报告跳过是否成功,因此如果无法保证,我可能需要修改客户端代码。非常感谢。您可以修复FileInputStream.skip()
问题:使用while
循环n-1
字节;然后,在循环之后,调用.read()中的
一次。如果它返回-1
,则跳过将达到EOF,否则跳过成功。另外,不要忘记在顶部检查n==0
。@KannanGoundan一个有趣的建议。当然,一个缺点是它至少需要从流中读取两次数据(一个跳过加上一个读取),这在某些情况下可能会影响性能。这看起来或多或少与Guava的ByTestStreams.skipFully
方法相同,因此它可能是正确的。