在上古时代,由于阅读设备垃圾,所以很多txt文件都被分割为以章为单位,一个完整的文件往往要占据一个文件夹,强迫症根本忍受不了。所以希望通过python对txt文件进行合并。


文章目录

  • 1.汉字转数字
  • 2. 字符排序
  • 3. 文本文档合并


1.汉字转数字

合并txt文件需要遵循一个前后顺序,如果文件名中包含数字是最好的,尤其是位数相同的数字,这时文件名读取函数os.listdir会自动按照数字顺序读取。然而,若文件名是通过汉字进行排序的,那就有些不妙了。

对于型如一千二百五十五这样的汉字,千、百、十的作用显然强于一、二、五,因为它们决定了位数。如果说类似一、二、五这样的数字可以直接通过字典转化为1,2,5,那么千、百十则需要对其前面的数字乘以1000,100以及10。

由于我要处理的文件一般不超过十万个,所以最大位数从万开始。

unitDict={"零":0,"":1,"一":1,"二":2,"两":2,"三":3,"四":4,"五":5,"六":6,"七":7,"八":8,"九":9}
decadeDict={"万":10000,"千":1000,"百":100,"十":10}
#十万以内的汉字转数字
def zh2num(name):
    val = 0
    for sym in decadeDict.copy():
        if sym in name:
            pre,name = name.split(sym)  #字符串分割
            val += decadeDict[sym]*unitDict[pre]
    if name != "":
        val += unitDict[name]
    return val

2. 字符排序

接下来,以汉字转数字为核心算法,来写一个字符排序的函数。由于我们不确定文件名中的序号到底是汉字还是数字,所以需要把二者都考虑进来,然后据此建立字典,通过字典的键对值进行排序,最后输出排好序的文件名列表。

# 如果字符串中存在中文数字,对其进行排序
def sortStr(files,flag=0):
    nums = "0123456789"
    zhs = list(unitDict.keys())+list(decadeDict.keys())
    sortDict = {}
    end = len(files)
    for f in files:
        nStr = "".join([c for c in list(f[:flag] if flag>0 else f) if c in nums])
        zStr = "".join([c for c in list(f[:flag] if flag>0 else f) if c in zhs])
        if nStr != "":
            sortDict[int(nStr)] = f
        elif zStr !="":
            sortDict[zh2num(zStr)] = f
        else:
            end += 1
            sortDict[end]=f
    return [sortDict[n] for n in np.sort(list(sortDict))]

需要注意的是,这个函数的适用条件非常有限,如果想应对更多的情况,还是需要继续改进的。

3. 文本文档合并

最后写出主程序,输入文件路径后,通过os.listdir读取文件夹中的文件名,需要注意,打开文件的时候可能会遇到一些诡异的字符,所以我们选择忽略错误errors="ignore

def emerge(path,flag=0):
    files = sortStr(os.listdir(path),flag)
    newTxt = open(path+".txt","w",encoding="GBK")
    
    path += "\\"
    for f in files:
        try:
            txt = open(path+f,"r",encoding='GBK',errors="ignore")
            newTxt.write(f.split(".txt")[0]+"\n")
            strs = txt.read()
            newTxt.write(strs+"\n")
        except Exception as e:
            print(path+f)
            print(e)
    newTxt.close()