作用:
从服务器端发送回来的未匹配数据报中提取数据,并依据匹配的数组和数据报的编号(均是服务器发送回来)与不完整文件进行重新组合,从而生成完整文件。
基本算法:
用一个currentindex变量记录当前数据块编号,
先读取一块返回的数据块,和它的对应编号index(前一个数据块的编号),
如果index>currentindex,根据currentindex从filematchindexs数组(匹配的数组)中读取blockindex(即应该先写入的匹配的数据块),并将currentindex改为index,
否则根据index读取blockindex,并将不完整文件的读取指针移动到blockindex*Block,
读取一块数据,并写入rebuild文件中,重复(index-currentindex)次,
再将此块返回数据块写入rebuild文件中,
重复以上过程知道返回数据报读取完,
再将剩余的不完整文件写入rebuild文件中。
注意点:
1. 采用随机文件读取,效率可能稍低,但是灵活。
2. 异常处理。
扫描二维码关注公众号,回复:
8529893 查看本文章
3. 比较重要的模块,而且稍有复杂度,待完善。
4. 需要加入后缀处理。
源码:
public void rebuidFile(String filehalf, InputStream inFileBack,
OutputStream rebuidOut) throws FileNotFoundException, IOException {
RandomAccessFile randomAccessFile = new RandomAccessFile(filehalf, "r");
BufferedInputStream backInput = null;
backInput = new BufferedInputStream(inFileBack);
byte halfBuffer[] = new byte[ServerCheckSumCreater.BLOCKSIZE];
byte backBuffer[] = new byte[ServerMatchStarter.DATATOTALSIZE];
int currentIndex = 0;
int amount = 0;
try {
// getMatchTable
// DataInputStream dataInputStream = new
// DataInputStream(inFileBack);
byte b[] = new byte[4];
inFileBack.read(b);
int matchnum = DataConvertUtils.bytes2int(b);
int matchindexs[] = new int[matchnum];
for (int i = 0; i < matchnum; i++) {
inFileBack.read(b);
matchindexs[i] = DataConvertUtils.bytes2int(b) - 1;
}
// dataInputStream.close();
//
// boolean rebuildSwitch = false;
// if (backInput.read(backBuffer) != -1) {
// byte indexFlag = backBuffer[MatchStarter.INDEXFLAGOFF];
// switch (indexFlag) {
// case DatagramType.ALLMATCH: {
//
// rebuildSwitch = true;
// }
// break;
// case DatagramType.ZEROMATCH: {
//
// // rebuildSwitch = true;
// }
// break;
// }
// }
while (backInput.read(backBuffer) != -1) {
int indexFlag = backBuffer[ServerMatchStarter.INDEXFLAGOFF];
if (indexFlag == DatagramType.UNMATCHDATA_END)
break;
int index = 0;
int length = backBuffer[ServerMatchStarter.LENGTHOFF];
byte[] data = new byte[length];
if (indexFlag == DatagramType.UNMATCHDATA_INDEX_VALID) {
// index valid
// seek to currentIndex*TestCreateCheckSum.BLOCKSIZE
// read index - currentIndex blocks of halffile
// write to rebuildfile
// currentIndex = index
byte[] indexbyte = new byte[4];
for (int i = 0; i < 4; i++) {
indexbyte[i] = backBuffer[ServerMatchStarter.INDEXOFF + i];
}
index = DataConvertUtils.bytes2int(indexbyte);
if (index > currentIndex) {
randomAccessFile.seek(ServerCheckSumCreater.BLOCKSIZE
* matchindexs[currentIndex]);
for (int i = 0; i < (index - currentIndex); i++)
if ((amount = randomAccessFile.read(halfBuffer)) != -1) {
rebuidOut.write(halfBuffer, 0, amount);
}
currentIndex = index;
}
}
// read a block_backfile and write to filerebuild
for (int i = 0; i < length; i++) {
data[i] = backBuffer[ServerMatchStarter.DATAOFF + i];// 待优化
}
rebuidOut.write(data);
}
// write remained halffile data
for (; currentIndex < matchnum; currentIndex++) {
int index = matchindexs[currentIndex];
randomAccessFile.seek(ServerCheckSumCreater.BLOCKSIZE * index);
if ((amount = randomAccessFile.read(halfBuffer)) != -1) {
rebuidOut.write(halfBuffer, 0, amount);
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
return;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}