001 Python之文件夹归并算法(实战17亿数据有序合并没问题,单线程)

Python之文件夹归并算法

1. github项目地址

github项目地址

2. 项目介绍

第一步:创建数据
  1. 首先打开CreateData模块,运行下该模块,你就能在本项目路径下的data下拿到生成的数据,用这个模拟文件夹归并
  2. 其次CreateData模块生成了50个文件,总共579M数据,文件夹内文件越多,本项目的优势越能体现出来
  3. 运行下Merge模块,然后两分钟五十三秒左右,你就能拿到579M数据组成的一个排好序的大文件,本项目经过了17亿级别的数据测试,没有丢失数据以及其他情况
创造数据代码
import os, time, random


class CreateData:
    def __init__(self, fileDir, fileCount):
        self.fileDir = fileDir
        self.fileCount = fileCount

    def createData(self):
        for i in range(self.fileCount):
            file = open(os.path.join(self.fileDir, "Data-%s.txt" % str(i + 1).zfill(2)), "w", encoding="utf-8",
                        errors="strict")
            for data in range(random.randrange(10), 5000000, 7):
                writeStr = str(data).zfill(7) + "\t" + str(data).zfill(7) + "\n"
                file.write(writeStr)


data = CreateData(r"data", 50)
data.createData()
整体算法代码
import time, os

'''
create by Luo 2017-7-22 14:53:21
'''
class Merge:
    def __init__(self, orginDir, objectPath):
        self.fileNameList = os.listdir(orginDir)  # 文件夹下所有文件名
        self.fileList = []  # 文件列表
        self.objectFile = open(objectPath, "w", -1, encoding="utf-8", errors="strict")  # 目标文件
        for fileName in self.fileNameList:  # 遍历添加文件到文件列表
            file = open(os.path.join(orginDir, fileName), "r", -1, encoding="utf-8", errors="strict")
            self.fileList.append(file)

    # 文件夹合并
    def mergeFile(self):
        print("开始文件夹合并:", time.ctime())
        list1 = []  # 用于装文件对象,文件读取的数据,以及排序的那一列数据
        # 循环拿到每一个文件的第一行数据并添加进列表
        for file in self.fileList:
            line = file.readline()
            if line:
                list1.append([file, [line, line.split("\t")[0]]])
            else:
                file.close()  # 剔除无用的文件
                self.fileList.remove(file)

        list1.sort(key=lambda x: x[1][1])  # 只进行一次排序

        while len(list1) != 0:
            # 将排序最小的数据写入文件,并剔除文件末尾的错位情况
            self.objectFile.write(list1[0][1][0])
            nowFile = list1[0][0]
            nowLine = nowFile.readline()
            list1.remove(list1[0])
            if nowLine:  # 过滤读到文件末尾的情况,并把该文件剔除
                # self.__insertAndSort(list1, [nowFile, [nowLine, nowLine.split("\t")[0]]])  # 插入排序,节省排序时间
                self.__helfInsert(list1, [nowFile, [nowLine, nowLine.split("\t")[0]]])  # 插入排序,节省排序时间
            else:
                nowFile.close()
        print("结束文件夹合并:", time.ctime())

    # 插入排序,节省排序时间
    def __insertAndSort(self, list1, listItem):
        for index in range(len(list1)):
            if listItem[1][1] <= list1[index][1][1]:
                list1.insert(index, listItem)
                break
        else:
            list1.append(listItem)

    # 二分法插入排序
    def __helfInsert(self, list1, listItem):
        num1 = listItem[1][1]
        low = 0
        length = len(list1)
        high = length - 1
        while low <= high:
            mid = (low + high) // 2
            if num1 < list1[mid][1][1]:
                high = mid - 1
            elif num1 > list1[mid][1][1]:
                low = mid + 1
            else:
                list1.insert(mid, listItem)
                break
        else:
            if low == length:
                list1.append(listItem)
            else:
                list1.insert(low, listItem)

    def __del__(self):
        self.objectFile.close()


orginDir = r"data"
objectPath = r"DirMergeSort.txt"

merge1 = Merge(orginDir, objectPath)
merge1.mergeFile()

# 二分法插入归并测试  50个文件 579M  耗时 0:02:53
# 开始文件夹合并: Sat Jul 22 09:00:14 2017
# 结束文件夹合并: Sat Jul 22 09:03:07 2017

# 插入排序归并测试  50个文件 579M  耗时 0:06:47
# 开始文件夹合并: Sat Jul 22 09:04:19 2017
# 结束文件夹合并: Sat Jul 22 09:11:06 2017
第三步:测试结果(文件越多,二分法插入排序的优势越大)
二分法插入归并测试  50个文件 579M  耗时 0:02:53
开始文件夹合并: Sat Jul 22 09:00:14 2017
结束文件夹合并: Sat Jul 22 09:03:07 2017

插入排序归并测试  50个文件 579M  耗时 0:06:47
开始文件夹合并: Sat Jul 22 09:04:19 2017
结束文件夹合并: Sat Jul 22 09:11:06 2017

总结

在你进行多文件合并的时候,很多时候你需要大量的两两合并对文件进行有序归并,本项目就是为了解决文件夹文件归并而出现的(前提是你文件夹中每个文件必须有序)。
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值