ご存知のとおり、md5 を使用して 2 つのファイルが同じかどうかを比較できます。デモを作成したときにエラーが発生しました。2 つのファイルを比較するために 2 つの方法を使用しました。方法 2 の方が成功しましたが、方法 1 は失敗しました。
注: test は元のビデオ ファイル、test2 はブロックに分割されて結合されたファイルです。どちらも同じデータサイズで普通に再生できます。
//方法1 失败
String s1 = DigestUtils.md5Hex("E:\\test.mp4");
String s2 = DigestUtils.md5Hex("E:\\test2.mp4");
if (s2.equals(s1)){
System.out.println("文件校验完整");
}
//方法2 成功
FileInputStream fileInputStream_merge = new FileInputStream(mergeFile);
FileInputStream fileInputStream_source = new FileInputStream(sourceFile);
String s1 = DigestUtils.md5Hex(fileInputStream_merge);
String s2 = DigestUtils.md5Hex(fileInputStream_source);
if (s2.equals(s1)){
System.out.println("文件校验完整");
}
情報を検索した後、
最初の方法は 2 つのコピーの MD5 値を計算することですが、2 つのコピーの MD5 値が異なる場合、2 つのコピーのメタデータが異なることが原因である可能性があります。メタデータにはファイルの作成時刻、変更時刻、アクセス時刻などの情報が含まれており、情報が異なると計算されるMD5値も異なります。
2 番目の方法は 2 つのコピーの MD5 値を計算し、2 つのコピーの MD5 値が同じである場合、2 つのコピーのメタデータが同じであるか、メタデータだけが異なるためである可能性がありますが、ファイル内容は同じです。2 番目の方法では、メタデータの違いに関係なく、ファイルのコンテンツのみがカウントされるためです。
まとめ: ファイルが整合性があるかどうかを比較するのは、内容を比較するのが一般的です。ストリームを使って操作してみましょう。ストリーム操作は io では遅いですが、占有メモリは少なく、ファイルを直接読み取る方法とは逆です。
//测试分块
@Test
public void testChunk() throws IOException {
//源文件
File sourceFile = new File("E:\\test.mp4");
//分块文件存储输出路径
String chunkFilePath="E:\\chunck\\";
//分块大小
int chunkSize=1024*1024*1;
//对块数向上取整
int chunkNum= (int) Math.ceil(sourceFile.length()*1.0/chunkSize);
//使用流从源文件读取数据
RandomAccessFile r = new RandomAccessFile(sourceFile, "r");
//缓存区
byte [] bytes=new byte[1024];
//循环写入文件
for (int i = 0; i < chunkNum; i++) {
//创建一个目标文件
File file = new File(chunkFilePath + i);
//从流中写到file
RandomAccessFile rw = new RandomAccessFile(file, "rw");
int len=-1;
while ((len=r.read(bytes))!=-1){
rw.write(bytes,0,len);
if (file.length()>=chunkSize) break;
}
rw.close();
}
r.close();
}
//测试合并
@Test
public void testMerge() throws IOException {
//块文件目录
File chunkFile = new File("E:\\chunck\\");
//源文件,用于比较md5值判断他们是否完整
File sourceFile = new File("E:\\test.mp4");
//合并后的文件
File mergeFile = new File("E:\\test2.mp4");
//取出所有分块文件
File[] files = chunkFile.listFiles();
//将数组转成list
List<File> fileList = Arrays.asList(files);
//对分块文件进行排序
Collections.sort(fileList, new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
return Integer.parseInt(o1.getName())-Integer.parseInt(o2.getName());
}
});
//向合并文件写流
RandomAccessFile rw = new RandomAccessFile(mergeFile, "rw");
//缓存区
byte[] bytes = new byte[1024];
//遍历分块文件,向合并的文件写
for (File file : fileList) {
//读取分块的流
RandomAccessFile r = new RandomAccessFile(file, "r");
int len=-1;
while ((len=r.read(bytes))!=-1){
rw.write(bytes,0,len);
}
r.close();
}
rw.close();
//合并文件完成后对文件进行md5校验
// FileInputStream fileInputStream = new FileInputStream(mergeFile);
// String s1 = DigestUtils.md5Hex("E:\\test.mp4");
// String s2 = DigestUtils.md5Hex("E:\\test2.mp4");
FileInputStream fileInputStream_merge = new FileInputStream("E:\\test.mp4");
FileInputStream fileInputStream_source = new FileInputStream("E:\\test2.mp4");
String s1 = DigestUtils.md5Hex(fileInputStream_merge);
String s2 = DigestUtils.md5Hex(fileInputStream_source);
if (s2.equals(s1)){
System.out.println("文件校验完整");
}