基于rsync同步算法的文件同步系统JAVA实现(四)——分析并发送不匹配数据块
2013-08-25 15:56
886 查看
作用:
利用不完整文件的校验块所构成的哈希表顺序查询完整文件的校验块,从而得出匹配情况,并返回不匹配数据块及其相应编号,当然还有一些控制信息。由于该过程比较复杂,所以最好设计一个数据报,便于客户端分析和重组文件。数据报格式:
|IndexFlag(1字节) | |Index(4字节) | |Length(1字节) | |Buffer(可变,<=127) |
|区别数据报种类 | |记录校验块编号 | |Buffer中所含的数据大小 | |未匹配数据 |
基本思想:
按顺序读取完整文件中的数据块并得到校验块,按照建立的哈希表进行查询,若匹配(滚动和md4均匹配),则读取下一个数据块,若不匹配,则读取下一个字节(类似滑动窗口),并将先前头一个字节加入数据报中,再进行匹配分析。注意点:
1. 数据报发送时机:数据报buffer字段满时,从不匹配到匹配时。2. 发送数据报之前写入Length字段。
3. 结尾处理后,最好发送匹配的编号,对客户端重组有利。
4. 一些IO异常处理。
5. 发送时并不直接发送到socket的输出流中,而是先写入本地文件,因为某些缓冲和接受顺序原因。
6. 此部分较为复杂,可能有许多不合理的地方,需要不断完善。
源码:
public void startMatch(String filetotal, InputStream inStreamCheckSum, OutputStream outStreamFIleBack, OutputStream outStreamMatchIndexs) throws IOException { BufferedInputStream inStreamFileTotal = new BufferedInputStream( new FileInputStream(filetotal)); // BufferedOutputStream outStreamFIleBack = new BufferedOutputStream( // outStreamBack); // DataOutputStream outStreamMatchIndexs = new DataOutputStream( // new BufferedOutputStream(outStreamMatchOrder)); DataInputStream bf = new DataInputStream(inStreamFileTotal); ServerCheckSumHashCreater testCreateHash = new ServerCreateHash(); testCreateHash.buildHashTable(inStreamCheckSum); byte[] bufferWindow = new byte[ServerCheckSumCreater.BLOCKSIZE]; int amount = 0;// 缓冲区实际数量 boolean newBufferSend = false; boolean lastmatchFlag = true; int bufferDataIndex = 0; long lastMatchIndex = 0; byte bufferSend[] = new byte[DATATOTALSIZE]; int matchindexs[] = new int[inStreamFileTotal.available() / ServerCheckSumCreater.BLOCKSIZE + 1]; int matchnum = 0; try { // 开始读取文件循环 while ((amount = bf.read(bufferWindow)) != -1) { SumChecking.checkSum_Adler32(bufferWindow, ServerCheckSumCreater.BLOCKSIZE); int matchflag = testCreateHash.checkMatch(bufferWindow, ServerCheckSumCreater.BLOCKSIZE); if (matchflag != -1) { lastMatchIndex++; matchindexs[matchnum++] = matchflag; } while (matchflag == -1) { if (lastmatchFlag == true) { lastmatchFlag = false; // writeIndexFlagTrue bufferSend[INDEXFLAGOFF] = DatagramType.UNMATCHDATA_INDEX_VALID; bufferSend[1] = (byte) (lastMatchIndex & 0xff); bufferSend[2] = (byte) ((lastMatchIndex & 0xff00) >> 8); bufferSend[3] = (byte) ((lastMatchIndex & 0xff0000) >> 16); bufferSend[4] = (byte) ((lastMatchIndex & 0xff000000) >> 24); } else if (newBufferSend) { // writeIndexFlagFalse bufferSend[INDEXFLAGOFF] = DatagramType.UNMATCHDATA_INDEX_INVALID; newBufferSend = false; } // readNextByte byte nextbyte = bf.readByte(); // addUnMatchByte bufferSend[DATAOFF + bufferDataIndex] = bufferWindow[0]; bufferDataIndex++; if (bufferDataIndex == DATAACTUALSIZE) { // writeDataLength bufferSend[LENGTHOFF] = (byte) bufferDataIndex; // sendBuffer outStreamFIleBack.write(bufferSend); bufferDataIndex = 0; newBufferSend = true; } System.arraycopy(bufferWindow, 1, bufferWindow, 0, amount - 1); bufferWindow[amount - 1] = nextbyte; // computeCheckSum matchflag = testCreateHash.checkMatch(bufferWindow, ServerCheckSumCreater.BLOCKSIZE); if (matchflag != -1) { lastMatchIndex++; matchindexs[matchnum++] = matchflag; } }// 未匹配内循环结束 if (!lastmatchFlag && !newBufferSend) { // writeDataLength bufferSend[LENGTHOFF] = (byte) (bufferDataIndex); outStreamFIleBack.write(bufferSend); bufferDataIndex = 0; // getLastMatchIndex } newBufferSend = false; lastmatchFlag = true; } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); if (bufferDataIndex > 0) { bufferSend[LENGTHOFF] = (byte) (bufferDataIndex); outStreamFIleBack.write(bufferSend); bufferDataIndex = 0; bufferSend[INDEXFLAGOFF] = DatagramType.UNMATCHDATA_INDEX_INVALID; } for (int i = 0; i < amount; i++) { bufferSend[DATAOFF + bufferDataIndex] = bufferWindow[i]; bufferDataIndex++; if (bufferDataIndex == DATAACTUALSIZE) { // writeDataLength bufferSend[LENGTHOFF] = (byte) bufferDataIndex; // sendBuffer outStreamFIleBack.write(bufferSend); bufferDataIndex = 0; } } if (bufferDataIndex > 0) { bufferSend[LENGTHOFF] = (byte) (bufferDataIndex); outStreamFIleBack.write(bufferSend); bufferSend[INDEXFLAGOFF] = DatagramType.UNMATCHDATA_INDEX_INVALID; bufferDataIndex = 0; } } finally { // wirteMatchIndexs bufferSend[INDEXFLAGOFF] = DatagramType.UNMATCHDATA_END; outStreamFIleBack.write(bufferSend); outStreamMatchIndexs.write(DataConvertUtils.int2bytes(matchnum)); for (int i = 0; i < matchnum; i++) { outStreamMatchIndexs.write(DataConvertUtils .int2bytes(matchindexs[i])); } out.println("matchnum:" + matchnum); out.println("matchindexs:"); out.println(Arrays.toString(matchindexs)); // //判断全部匹配和全部不匹配的特殊情况 // if (matchnum == 0) { // bufferSend[INDEXFLAGOFF] = DatagramType.ZEROMATCH; // } else if (unmatchnum == 0) { // bufferSend[INDEXFLAGOFF] = DatagramType.ALLMATCH; // } // try { // inStreamFileTotal.close(); // outStreamFIleBack.close(); // outStreamMatchIndexs.close(); // } catch (IOException e) { // e.printStackTrace(); // } } }
相关文章推荐
- 基于rsync同步算法的文件同步系统JAVA实现(五)—— 重组数据块
- 基于rsync同步算法的文件同步系统JAVA实现(二)——校验码的生成
- 基于rsync同步算法的文件同步系统JAVA实现(三)——校验码哈希表的建立
- 基于rsync同步算法的文件同步系统JAVA实现(一)——项目介绍
- 基于rsync同步算法的文件同步系统JAVA实现(一)——项目介绍
- 基于差异的文件同步算法-The rsync algorithm
- Rsync实现文件同步的算法(转载)
- rsync实现网站的备份,文件的同步,不同系统的文件的同步,如果是windows的话,需要windows版本cwrsync【文件从本地上传到linux服务器有什么更好的工具?】
- 基于cron、rsync和ssh免密码登录实现Linux系统间自动同步~
- linux下基于rsync + find命令实现文件同步机制
- java基于jcifs.smb实现远程发送文件到服务器
- Centos7.0系统下Rsync+sersync实现多文件数据实时增量同步 推荐
- “基于关键字匹配的文本过滤系统”配置文件的设计和实现(C/C++源码)
- Rsync实现Windows系统与Linux文件同步
- “基于关键字匹配的文本过滤系统”配置文件的设计和实现(C/C++源码)
- 基于rsync和inotify实现web网站文件的同步,并基于IPTABLES做用户限制 推荐
- Linux系统文件同步rsync+ssh+inotify+unison实现
- 基于rsync+inotify实现文件实时同步
- java开发系统内核:实现基于FAT12文件系统的dir命令
- 基于java最短路径算法公交查询系统的设计与实现