在java.io.InputStream类中定义了skip这个方法。在API中的描述如下:

skip

public long skip(long n)
throws IOException

Skips over and discards ​​n​​ bytes of data from this input stream. The ​​skip​​ method may, for a variety of reasons, end up skipping over some smaller number of bytes, possibly ​​0​​. This may result from any of a number of conditions; reaching end of file before​​n​​ bytes have been skipped is only one possibility. The actual number of bytes skipped is returned. If ​​n​​ is negative, no bytes are skipped.

The ​​skip​​ method of this class creates a byte array and then repeatedly reads into it until ​​n​​ bytes have been read or the end of the stream has been reached. Subclasses are encouraged to provide a more efficient implementation of this method. For instance, the implementation may depend on the ability to seek.

 

Parameters:

​n​​ - the number of bytes to be skipped.

Returns:

the actual number of bytes skipped.

Throws:

​IOException​​ - if the stream does not support seek, or if some other I/O error occurs.

翻译如下:

 skip(long n) throws ​​IOException​

跳过和丢弃此输入流中数据的 n 个字节。出于各种原因,​skip​ 方法结束时跳过的字节数可能小于该数,也可能为 ​0​。导致这种情况的原因很多,跳过 ​n​ 个字节之前已到达文件末尾只是其中一种可能。返回跳过的实际字节数。如果 ​n​ 为负,则不跳过任何字节。

此类的 ​​skip​​ 方法创建一个 byte 数组,然后重复将字节读入其中,直到读够 ​​n​​ 个字节或已到达流末尾为止。建议子类提供此方法更为有效的实现。例如,可依赖搜索能力的实现。

n


要跳过的字节数。

return


跳过的实际字节数。

Throws

​IOException​​: 

如果流不支持搜索,或者发生其他 I/O 错误。

 

同时,其子类FileInputStream中也继承了skip这个方法。如API中所描述的,skip方法会存在跳过的字节数小于预期的情况。如果不对返回值进行处理的话,很容易忽视这个问题,导致结果错误。最近在看baksmali的源码,其中有一个简单而巧妙的方法来避过skip方法的这个弊端。

在分片上传文件的时候,进行skip,该处理手段非常重要。



FileInputStream in = new FileInputStream(file);
int at = offset;
while(at > 0) {
long realSkip = in.skip(at);
if (realSkip == -1) {
throw new RuntimeException(file + ": unexpected EOF");
}
at -= realSkip;
}