如何通过编程查找重复文件及Android手机全机重复文件查找方法
问题1:编程实现重复文件查找的方案
核心逻辑是分层筛选,尽可能降低不必要的哈希计算量,提升扫描效率:
- 第一步:遍历目标目录下的所有文件,过滤目录、符号链接等非普通文件对象,记录所有文件的路径、大小信息
- 第二步:按文件大小分组,只有文件大小完全一致的才可能是重复文件,直接排除大小不同的文件,可降低90%以上的后续计算量
- 第三步:对同大小分组内的文件,先计算文件前
16KB的哈希值(MD5或SHA-256均可),再次分组,排除前16KB哈希不同的文件 - 第四步:对剩余的同大小、同前16KB哈希的文件,计算全文件哈希值,哈希值完全相同的判定为重复文件
示例Python核心代码如下:
import os import hashlib def get_file_hash(file_path, block_size=65536, partial=False): hash_obj = hashlib.sha256() with open(file_path, 'rb') as f: while True: block = f.read(block_size) if not block: break hash_obj.update(block) if partial: # 仅读取前一块用于快速筛选 break return hash_obj.hexdigest() def find_duplicates(root_path): size_map = {} # 第一步:按文件大小分组 for root, _, files in os.walk(root_path): for file in files: file_path = os.path.join(root, file) try: file_size = os.path.getsize(file_path) except OSError: continue if file_size not in size_map: size_map[file_size] = [] size_map[file_size].append(file_path) # 过滤只有一个文件的大小组 size_map = {k:v for k,v in size_map.items() if len(v)>=2} dup_groups = [] for file_list in size_map.values(): # 第二步:按前16KB哈希分组 partial_hash_map = {} for fp in file_list: try: p_hash = get_file_hash(fp, partial=True) except OSError: continue if p_hash not in partial_hash_map: partial_hash_map[p_hash] = [] partial_hash_map[p_hash].append(fp) partial_hash_map = {k:v for k,v in partial_hash_map.items() if len(v)>=2} # 第三步:按全文件哈希分组 for plist in partial_hash_map.values(): full_hash_map = {} for fp in plist: try: f_hash = get_file_hash(fp) except OSError: continue if f_hash not in full_hash_map: full_hash_map[f_hash] = [] full_hash_map[f_hash].append(fp) dup_groups.extend([v for v in full_hash_map.values() if len(v)>=2]) return dup_groups
额外注意事项:
- 大于4GB的大文件可以随机抽取多块位置的哈希做校验,不需要全量计算,大幅降低资源消耗
- 扫描过程要跳过系统锁文件、无权限访问的文件,避免程序崩溃
问题2:Android整机存储重复文件扫描方案
分两种权限场景实现:
无需Root的方案
- 先申请对应存储权限:Android 13及以上需要申请
READ_MEDIA_IMAGES、READ_MEDIA_VIDEO、READ_MEDIA_AUDIO权限;Android 12及以下需要申请READ_EXTERNAL_STORAGE权限;如果要扫描所有类型的文件需要申请MANAGE_EXTERNAL_STORAGE权限,需引导用户到系统设置页手动开启 - 优先通过
MediaStore接口查询所有公共存储文件的路径、大小信息,比直接遍历文件系统速度快3~5倍,Kotlin示例查询代码:
val projection = arrayOf(MediaStore.Files.FileColumns.DATA, MediaStore.Files.FileColumns.SIZE) val cursor = contentResolver.query(MediaStore.Files.getContentUri("external"), projection, null, null, null) cursor?.use { val dataIndex = it.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA) val sizeIndex = it.getColumnIndexOrThrow(MediaStore.Files.FileColumns.SIZE) while (it.moveToNext()) { val filePath = it.getString(dataIndex) val fileSize = it.getLong(sizeIndex) // 存入大小分组做后续筛选 } }
- 后续判定重复文件的逻辑和上面的编程实现逻辑完全一致,扫描完成后可按图片、视频、文档、安装包等分类展示重复文件,供用户选择清理
已Root的方案
- 获取根目录读写权限后,直接遍历
/根目录下的所有分区(包括系统分区、内置存储、外置SD卡等),复用相同的哈希校验逻辑扫描即可,注意不要随意删除系统分区的重复文件,避免系统运行异常
内容的提问来源于stack exchange,提问作者Thoriya Prahalad
相关产品推荐
相关产品推荐

