原理
通过把照片进行hash转换,相同hash值的认为是相同照片,打印到本地文件中供二次确认。
代码
import java.io.*;
import java.math.BigInteger;
import java.nio.file.Files;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;
public class RemoveDuplicatePhotos {
public static void main(String[] args) {
File folder = new File("/path/to/your/photos"); // 替换为你的照片所在的文件夹
Map<String, String> map = new ConcurrentHashMap<>();
ExecutorService executor = Executors.newFixedThreadPool(10); // 创建一个固定大小的线程池
try (PrintWriter writer = new PrintWriter(new File("duplicates.txt"))) {
processFolder(folder, map, writer, executor);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
executor.shutdown(); // 关闭线程池
}
private static void processFolder(File folder, Map<String, String> map, PrintWriter writer, ExecutorService executor) {
File[] files = folder.listFiles();
if (files == null) {
System.out.println("Folder does not exist or is not a directory");
return;
}
for (File file : files) {
if (file.isDirectory()) {
processFolder(file, map, writer, executor);
} else {
executor.submit(() -> {
try {
String hash = calculateHash(file, "SHA-256");
String existingFile = map.putIfAbsent(hash, file.getPath());
if (existingFile != null) {
writer.println("Duplicate file found: " + file.getPath());
writer.println("It is a duplicate of: " + existingFile);
}
} catch (IOException | NoSuchAlgorithmException e) {
e.printStackTrace();
}
});
}
}
}
private static String calculateHash(File file, String algorithm) throws IOException, NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance(algorithm);
try (DigestInputStream dis = new DigestInputStream(new FileInputStream(file), md)) {
byte[] buffer = new byte[1024];
while (dis.read(buffer) != -1) ; //empty loop to clear the data
md = dis.getMessageDigest();
}
// bytes to hex
BigInteger bi = new BigInteger(1, md.digest());
return String.format("%032x", bi);
}
}
判断某个文件夹的相片在其他文件夹中是否全都有
import java.io.*;
import java.math.BigInteger;
import java.nio.file.Files;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;
public class CheckFilesExist {
public static void main(String[] args) {
File folder1 = new File("/path/to/your/first/folder"); // 替换为你的第一个文件夹
File folder2 = new File("/path/to/your/second/folder"); // 替换为你的第二个文件夹
Map<String, String> map1 = new ConcurrentHashMap<>();
Map<String, String> map2 = new ConcurrentHashMap<>();
ExecutorService executor = Executors.newFixedThreadPool(10); // 创建一个固定大小的线程池
processFolder(folder1, map1, folder2, executor);
processFolder(folder2, map2, null, executor);
executor.shutdown(); // 关闭线程池
while (!executor.isTerminated()) ; // 等待所有任务完成
for (String hash : map2.keySet()) {
if (!map1.containsKey(hash)) {
System.out.println("File " + map2.get(hash) + " does not exist in the first folder");
}
}
}
private static void processFolder(File folder, Map<String, String> map, File excludeFolder, ExecutorService executor) {
File[] files = folder.listFiles();
if (files == null) {
System.out.println("Folder does not exist or is not a directory");
return;
}
for (File file : files) {
if (file.isDirectory()) {
if (excludeFolder != null && file.equals(excludeFolder)) {
continue;
}
processFolder(file, map, excludeFolder, executor);
} else {
executor.submit(() -> {
try {
String hash = calculateHash(file, "SHA-256");
map.put(hash, file.getPath());
} catch (IOException | NoSuchAlgorithmException e) {
e.printStackTrace();
}
});
}
}
}
private static String calculateHash(File file, String algorithm) throws IOException, NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance(algorithm);
try (DigestInputStream dis = new DigestInputStream(new FileInputStream(file), md)) {
byte[] buffer = new byte[1024];
while (dis.read(buffer) != -1) ; //empty loop to clear the data
md = dis.getMessageDigest();
}
// bytes to hex
BigInteger bi = new BigInteger(1, md.digest());
return String.format("%032x", bi);
}
}