62,610
社区成员
发帖
与我相关
我的任务
分享
import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
public class FileCompare {
static final int BufferSize = 32 * 1024;
interface ComparedHandler {
void onCompared(File f1, File f2, boolean equal);
}
public static void main(String[] args) {
final String path1 = "/path/a";
final String path2 = "/path/b";
doCompare(new File(path1), new File(path2), (File f1, File f2, boolean equal)->{
//TODO 处理比较结果。
System.out.println(String.format("文件 %s : %s , %s", equal?"相同":"不同", f1.getPath(), f2.getPath()));
});
}
private static void doCompare(File f1, File f2, ComparedHandler handler) {
if (f1.exists() && f2.exists()) {
// 只比较同名的目录和文件
if (f1.isDirectory() && f2.isDirectory()) {
Set<String> dn1 = Arrays.stream(f1.listFiles(f->f.isDirectory())).map(f->f.getName()).collect(Collectors.toSet());
Set<String> dn2 = Arrays.stream(f2.listFiles(f->f.isDirectory())).map(f->f.getName()).collect(Collectors.toSet());
dn1.retainAll(dn2);//两个集合的交集
for (String name : dn1) {
doCompare(new File(f1, name), new File(f2, name), handler);
}
Set<String> fn1 = Arrays.stream(f1.listFiles(f->f.isFile())).map(f->f.getName()).collect(Collectors.toSet());
Set<String> fn2 = Arrays.stream(f2.listFiles(f->f.isFile())).map(f->f.getName()).collect(Collectors.toSet());
fn1.retainAll(fn2);//两个集合的交集
for (String name : fn1) {
doCompare(new File(f1, name), new File(f2, name), handler);
}
} else if (f1.isFile() && f2.isFile()) {
if (f1.length() == f2.length()) {
if (f1.length() <= BufferSize) { // 小文件的数据比较
byte[] d1 = new byte[(int)f1.length()];
byte[] d2 = new byte[(int)f2.length()];
try (FileInputStream fis1 = new FileInputStream(f1);
FileInputStream fis2 = new FileInputStream(f2)) {
fis1.read(d1);
fis2.read(d2);
handler.onCompared(f1, f2, Arrays.equals(d1, d2));
} catch (IOException e) {
e.printStackTrace();
}
} else { // 大文件的数据比较
try (RandomAccessFile raf1 = new RandomAccessFile(f1, "r");
RandomAccessFile raf2 = new RandomAccessFile(f2, "r")){
FileChannel ch1 = raf1.getChannel();
FileChannel ch2 = raf2.getChannel();
long length = f1.length();
long position = 0;
boolean equal = true;
for(int bufferSize = 0; position < length; position += bufferSize) {
bufferSize = Math.min(BufferSize , (int)(length-position));
MappedByteBuffer buf1 = ch1.map(FileChannel.MapMode.READ_ONLY, position, bufferSize);
MappedByteBuffer buf2 = ch2.map(FileChannel.MapMode.READ_ONLY, position, bufferSize);
if (!buf1.equals(buf2)) {
equal = false;
break;
}
}
handler.onCompared(f1, f2, equal);
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
handler.onCompared(f1, f2, false);
}
}
}
}
}
文件数据的比较,还得是二进制数据的比较。
不太清楚实际的图片大小,如果都是小文件的话,可以直接全部读取到内存当中进行比较。
大文件(比如视频文件)可以使用内存映射形式的缓存进行比较,效率要高。
想进一步提升效率,可以考虑使用多线程,但是,效果可能不会太明显,因为瓶颈还是在IO访问上面。
package test;
import java.io.File;
import java.util.*;
public class Tester {
public static void main(String[] args) {
Tester tester=new Tester();
Map<String, String> filesNameMap2 = tester.getFilesNameMap("xxx");
Map<String, String> filesNameMap1 = tester.getFilesNameMap("xxx");
for (String fileName:filesNameMap1.keySet()
) {
if(filesNameMap2.containsKey(fileName)){
//比较
}else{
System.out.println("不相等:"+fileName);
}
}
}
public Map<String,String> getFilesNameMap(String filePath){
File file=new File(filePath);
String[] filesName = file.list();
Map<String, String> map=new HashMap<String, String>();
if(filesName==null)return map;
for(String eachFile:filesName){
map.put(eachFile,eachFile);
}
System.out.println(filesName.length);
return map;
}
}
package test;
import java.io.File;
import java.util.*;
public class Tester {
public static void main(String[] args) {
Tester tester=new Tester();
Map<String, String> filesNameMap2 = tester.getFilesNameMap("xxx");//XXX是文件路径
Map<String, String> filesNameMap1 = tester.getFilesNameMap("xxx");
for (String fileName:filesNameMap1.keySet()
) {
if(filesNameMap2.containsKey(fileName)){
//比较
}else{
System.out.println("不相等:"+fileName);
}
}
}
public Map<String,String> getFilesNameMap(String filePath){
File file=new File(filePath);
File[] files = file.listFiles();
Map<String, String> map=new HashMap<String, String>();
if(files==null)return map;
for(File eachFile:files){
map.put(eachFile.getName(),eachFile.getName());
}
System.out.println(files.length);
return map;
}
}