作者:曾家宏惠茹冠宇 | 来源:互联网 | 2023-10-09 20:12
问题是这样的:现在服务器端有两个文件夹,里面的文件都是文件名为MD5后的字符串并且没有文件后缀。这两个文件夹里有少部分重复的文件(指文件名重复即认为重复)并且少量文件存,icod
问题是这样的:现在服务器端有两个文件夹,里面的文件都是文件名为MD5后的字符串并且没有文件后缀。这两个文件夹里有少部分重复的文件(指文件名重复即认为重复)并且少量文件存在后缀名(这个也是不需要的)
一共有200万到300万的文件,20多个GB。
如果考虑速度的话最好可以使用hash表,但是几百万的文件建立map要消耗很大的空间,这里牺牲一定的准确性采用布隆过滤器
#!/usr/bin/python
# -*- coding: utf-8 -*-
# author:shq
import BitVector
import os
class Hash(object): # 哈希函数用来将元素映射到位向量中
def __init__(self, bit_size, seed):
self.bit_size = bit_size
self.seed = seed
def hash(self, string):
result = 0
for i in xrange(len(string)):
result += self.seed * result + ord(string[i]) # 哈希值计算公式
# 把hash值映射到比特向量中,&位运算保证返回的整数小于bit_size-1(不等0时)
return (self.bit_size - 1) & result
class Bloom_Filter(object):
'''
这个布隆过滤器首先需要:
1、一个位向量
2、n个种子用来生成hash函数
3、n个hash函数(用来映射位置)
'''
def __init__(self):
self.BIT_SIZE = 1 <<21
self.bitset = BitVector.BitVector(size=self.BIT_SIZE)
self.seeds = [12, 23, 34, 45, 56, 67, 78, 89]
self.hash_fun_list = [Hash(self.BIT_SIZE, seed) for seed in self.seeds]
def insert(self, string):
for hash_fun in self.hash_fun_list:
i = hash_fun.hash(string)
self.bitset[i] = 1
def judge_exist(self, string):
if string is None:
return False
for hash_fun in self.hash_fun_list:
i = hash_fun.hash(string)
if self.bitset[i] == 0:
return False
return True
def get_file_name(file_dir_1, file_dir_2):
'''
:param file_dir_1: 存储进过滤器的文件夹
:param file_dir_2: 被查找的文件夹
:return:
'''
test_BF = Bloom_Filter()
# 文件夹1的文件映射进过滤器
for _, _, files in os.walk(file_dir_1):
for file in files:
if '.' in file: # 去除后缀
os.rename(file_dir_1 + '/' + file, file_dir_1 + '/' + file.split('.')[0])
file = file.split('.')[0]
test_BF.insert(file)
# 判断文件夹2的文件是存在于过滤器
for _, _, files in os.walk(file_dir_2):
for file in files:
if '.' in file: # 去除后缀
os.rename(file_dir_2 + '/' + file, file_dir_2 + '/' + file.split('.')[0])
file = file.split('.')[0]
if test_BF.judge_exist(file):
change_time_1 = os.stat(file_dir_1 + '/' + file).st_mtime
change_time_2 = os.stat(file_dir_2 + '/' + file).st_mtime
if change_time_1 > change_time_2:
print u'删除:',file_dir_2 + '/' + file
os.remove(file_dir_2 + '/' + file)
else:
print u'删除:', file_dir_1 + '/' + file
os.remove(file_dir_1 + '/' + file)