python 实现文件内容去重
文本内容去重有很多很简单的方法可以实现,很多编辑器自带去除重复行的功能。写这篇文章的原因主要有两个
- 有的文本文件很大,超出了编译器能读取的范围
- 能有代码解决的代码解决,写好代码可以在其他代码中调用,更方便使用
简单的可以分为两种情况小文件和大文件,先来看小文件去重实现。如同把大象关冰箱一样分三步:
- 第一步,读取文件每一行,并处理掉换行符
- 第二步,将文件内容去重
- 第三步,写到新文件里(把冰箱门关上)
上代码
def file_remove_same(input_file, output_file):
"""
针对小文件去重
:param input_file: 输入文件
:param out_file: 去重后出文件
:return:
"""
with open(input_file, 'r', encoding='utf8') as f, open(output_file, 'a', encoding='utf8') as ff:
data = [item.strip() for item in f.readlines()] # 针对最后一行没有换行符,与其他它行重复的情况
new_data = list(set(data))
ff.writelines([item + '\n' for item in new_data if item]) # 针对去除文件中有多行空行的情况
对于大文件几十个G那种(更大的也别放在本地了,放数据库)就不能加载到内存中了,强行加载到内存中直接报内存错误
解决方案是:将文件按行读取,根据内容生成一个指纹(md5值或者其他唯一可识别的值),将指纹存集合中,当逐行读取的过程中判断集合中是否已经含有该行元素的指纹。如果指纹没有添加到集合中,则添加指纹到集合中并将此行追加输出到输出文件中。如果指纹已经在集合中了,说明此行与上面的某一行重复。
def gen_md5(data):
"""
生成md5
:param data: 字符串数据
:return:
"""
md5 = hashlib.md5()
md5.update(data.encode('utf-8'))
return md5.hexdigest()
def big_file_remove_same(input_file, output_file):
"""
针对大文件文件去重(将文件文件写在一行的,没有办法去重)
:param input_file:
:param output_file:
:return:
"""
finger_print_set = set()
with open(input_file, 'r', encoding='utf8') as f, open(output_file, 'w', encoding='utf8') as ff:
for line in f:
line_string = line.strip()
finger_print = gen_md5(line_string)
if finger_print not in finger_print_set:
finger_print_set.add(finger_print)
ff.write(line)
这样解决大小文件去重的问题 还有一种极端情况,就是指纹集合非常大,将内存占用溢出。这种情况几乎不会遇到,做一个大致的估计:当这个指纹集合内存占用到3G的时候,按照集合的占用效率大致是67%算,就能容纳2G的指纹,指纹按照md5值计算,就能容纳6710万行数据 。