目录
思路
1. 读取所有需要比较的文件,将文件内容转换为字符串。
2. 对每个文件内容进行哈希计算,生成唯一的哈希值。
3. 将所有文件的哈希值存储在一个哈希表中,检查是否存在相同的哈希值。
4. 如果存在相同的哈希值,则说明两个文件内容相同,可以将其标记为重复文件。
5. 最后输出所有重复文件的路径。
代码实现
package com.xzm.file;
import java.io.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
/**
* @Description 文件进行Hash去重
* @Author XueZhimin
* @CreateTime 2023-05-04 14:08
*/
public class FileDistinctHash {
public static void main(String[] args) {
//文件检查的目录
String directoryPath = "E:\\Programming_Lab";
//获取当前目录下所有文件
List<File> files = getFiles(directoryPath);
//定义一个hashMap用来检测hash,Key 存Hash值,Value存放 相同Hash值的集合
Map<String, List<File>> fileMap = new HashMap<>();
for (File file : files) {
//读取内容
String fileContent = getFileContent(file);
//将内容转换hash值
String hash = getHash(fileContent);
//当Hash相同,添加到Value集合
if (fileMap.containsKey(hash)) {
fileMap.get(hash).add(file);
} else {
//不相同就已Hash为Key,创建新的Value的List
List<File> fileList = new ArrayList<>();
fileList.add(file);
fileMap.put(hash, fileList);
}
}
//获取HashMap中所有的Value ,当Value的长度大于1就说明文件不是唯一的Hash值
for (List<File> fileList : fileMap.values()) {
if (fileList.size() > 1) {
System.out.println("Duplicate files(重复文件):");
//对相同Hash值的文件遍历输出
for (File file : fileList) {
System.out.println(file.getAbsolutePath());
}
}
}
}
/**
* 将目录下所有的文件存放到集合中
*
* @param directoryPath 目录
* @return
*/
private static List<File> getFiles(String directoryPath) {
File directory = new File(directoryPath);
List<File> fileList = new ArrayList<>();
if (!directory.isDirectory()) {
return fileList;
}
File[] files = directory.listFiles();
if (files == null) {
return fileList;
}
for (File file : files) {
if (file.isFile()) {
fileList.add(file);
} else if (file.isDirectory()) {
fileList.addAll(getFiles(file.getAbsolutePath()));
}
}
return fileList;
}
/**
* 读取文件中的内容
*
* @param file
* @return
*/
private static String getFileContent(File file) {
StringBuilder sb = new StringBuilder();
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
/**
* 字符串采用MD5算法转hash值
*
* @param input
* @return
*/
private static String getHash(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(input.getBytes());
return bytesToHex(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
/**
* 二进制转十六进制数据
*
* @param bytes
* @return
*/
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}