python 实现文件内容去重

   文本内容去重有很多很简单的方法可以实现,很多编辑器自带去除重复行的功能。写这篇文章的原因主要有两个

  1. 有的文本文件很大,超出了编译器能读取的范围
  2. 能有代码解决的代码解决,写好代码可以在其他代码中调用,更方便使用

 简单的可以分为两种情况小文件和大文件,先来看小文件去重实现。如同把大象关冰箱一样分三步:

  • 第一步,读取文件每一行,并处理掉换行符
  • 第二步,将文件内容去重
  • 第三步,写到新文件里(把冰箱门关上)

 上代码

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万行数据 。