InputStream 的截取
在进行一些断点续传的操作中,有时候我们获取的数据源并不是从一个url链接中获取的,而是从一个数据流中拿到的,那么HttpURLConnection提供给我们的setRequestProperty(“Range”,“byte=”)这个数据分段方法便不能适用于我们的需求了,那么对文件的IO流进行一些必要的操作,才能够满足我们的使用需求。下面进行介绍如何实现文件输入流的截取
- 生成断点数组
首先应该根据你的线程数目以及文件的总大小生成各个断点的起末点的数组
long[] startPos = new long[threadNum];//保存每个线程下载数据的起始位置
long[] endPos = new long[threadNum];//保存每个线程下载数据的截至位置.
long blockFileSize = fileLength%threadNum == 0?fileLength/threadNum:fileLength/threadNum+1;
private void setBreakPoint(long[] startPos,long[] endPos, int threadNum, long blockFileSize, long fileLength) throws IOException {
//未续传时初始化
for (int i=0; i<threadNum;i++){
startPos[i] = i * blockFileSize;
if (i==threadNum-1){
endPos[i] = fileLength;
}else {
endPos[i] = blockFileSize*(i+1)-1;
}
log.info("thre thread" + (i) + " startPos:" + startPos[i] + ", endPos: " + endPos[i]);
}
}
- 根据起始点截取需要的流
首先利用RandomAccessFile 类将源文件的流定位到需要截取的位置,然后利用ByteArrayOutputStream类拿到读取到的流,此时,拿到的流为ByteArrayOutputStream 形式,还可以通过toByteArray()实现将流转换为byte[]
public static byte[] interceptStreamAsByteArray(InputStream in, long startPos, long endPos, String fileName) throws IOException {
if (in == null){
return new byte[0];
}
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
RandomAccessFile rFile = new RandomAccessFile(fileName, "r");
OutputStream outputStream = null;
rFile.seek(startPos);
long byteSize = endPos - startPos;
byte[] bytes = new byte[(int) byteSize];
int s = rFile.read(bytes);
output.write(bytes, 0, s);
}catch (FileNotFoundException e){
e.printStackTrace();
}
return output.toByteArray();
}
以上为截取并转换为byte[],如果最终需要的仍是一个InputStream的话,可以利用ByteArrayInputStream方法将byte[]转化为InputStream
InputStream downFileIns = new ByteArrayInputStream(downFileByte);//byte[]=>InputStream
以上