最近写一个网络下载软件,需要使用java.IO.InputStream.skip(long n) 方法,它的作用是从输入流中跳过 n 个字节,比如 inputStream.skip(12),就是从inputStream中读最近写一个网络下载软件,需要使用取数据时,跳过前 12 个字节,从第13个字节读取,方法的返回值就是实际跳过的字节数
Java.IO.InputStream.skip(long n)方法,按道理返回值应该等于输入的参数 n (the actual number of bytes skipped.),但是它的我使用的时候,返回值往往小于 n,出错!
Java官方文档指出这个问题,建议自己去写一个方法来实现这个功能(Subclasses are encouraged to provide a more efficient
implementation of this method. For instance, the implementation may depend on the ability to seek),似乎说这个方法能否成功,也要取 决于机器的能力。
其实,如果自己写一个方法,思路就是从头开始读取,等到读到 n 时,再使用,这恰恰就是Java 源码中 InputStream.skip 的思路,一下是自己
写的一个方法:
/*重写了Inpustream 中的skip(long n) 方法,将数据流中起始的n 个字节跳过*/
private long skipBytesFromStream(InputStream inputStream, long n) {
long remaining = n;
// SKIP_BUFFER_SIZE is used to determine the size of skipBuffer
int SKIP_BUFFER_SIZE = 2048;
// skipBuffer is initialized in skip(long), if needed.
byte[] skipBuffer = null;
int nr = 0;
if (skipBuffer == null) {
skipBuffer = new byte[SKIP_BUFFER_SIZE];
}
byte[] localSkipBuffer = skipBuffer;
if (n <= 0) {
return 0;
}
while (remaining > 0) {
try {
nr = inputStream.read(localSkipBuffer, 0,
(int) Math.min(SKIP_BUFFER_SIZE, remaining));
} catch (IOException e) {
e.printStackTrace();
}
if (nr < 0) {
break;
}
remaining -= nr;
}
return n - remaining;
}
其实这个方法和Java官方源码的skip方法完全一样,只不过多加了一个 InputStream 的参数,当使用 inputStream来跳过 n 个字节时,可以使用这个方法。唯一不明白的就是不知道为什么同样一个方法,放在java 源码中调用会失败,但是自己写的却完全正常,求解…
不过上面的方法一般可以用来读取本地文件,但是如果是从网络下载资源的话,上述方法就根本没有实用性了(比如断点续传)。现在找到一个比较规范的方法:
HttpURLConnection con = null;
try {
con = (HttpURLConnection) u.openConnection();
con.setConnectTimeout(10000);// 设置连接超时为10秒
con.setRequestMethod("GET");
// 设置断点续传得起始与终止位置
long realPos = startPos + pausePos;
con.setRequestProperty("Range", "bytes=" + realPos + "-" + endPos);
con.setUseCaches(true);
InputStream inStream = con.getInputStream();//得到输入流
} catch (Exception exc) {
}
上面的方法就是使用HTTP来设置一个文件的下载范围(realPos-endPos),这样,从网络向下传输的时候,就会自动从realPos开始传输数据流,一直到endPos为止。