python文本文件合并软件 文件合并软件

简介

把多个文本合成一个文件

下载软件

使用python写的文本文件合并软件

文本合并软件,界面由三个容器组成,上方是文件列表显示窗口,中间是一行按钮,下方是操作提示窗口。文件列表显示窗口使用tk.Treeview控件,包括文件序号、文件路径和文件编码。操作提示窗口使用tk.Text控件。

这个软件的功能包括:

选择目录:扫描文件后缀,转小写等于txt的文件,并将它们添加到文件列表显示窗口。

移除:从文件列表中移除选中的文件。

上移:将选中的文件往上移一格。

下移:将选中的文件往下移一格。

合并文件:将文件列表中的文件按照从上往下的顺序合并。

清空列表:清空文件列表显示窗口内容,为下一个文件夹合并做准备。

在合并文件之前,需要先转换文件编码。具体过程如下:

使用二进制方式读取文件。

使用chardet.detect检测文件编码。

如果检测到的编码不是None或文件长度大于0,则将文件内容解码为unicode。

将unicode编码的文件内容转换为utf-8编码。

最后,将文件列表中的文件按照从上往下的顺序合并。

设计过程



=============================================================
文本合并软件
窗口布局 3个容器
上 文件列表显示窗口
中 按钮 排成一行
下 操作提示窗口

2个窗口
1.文件列表显示窗口 tk.Treeview ,有两个属性 1.序号 2.文件路径 3.文件编码,使用chardet.detect. (需要有拖文件夹到里面自动识别功能
2.操作提示窗口 tk.Text

按钮区
1.选择目录:扫描文件后缀,转小写等于txt的文件
2.移除
3.上移,把文件往上移
4.下移
5.合并文件
6.清空列表 ,清空文件列表显示窗口内容 ,为下一个文件夹合并做准备


合并文件过程
转换文件编码过程
先把文件用二进制读取,
if encoding != 'None' or length >= 0:
文件能容.decode(encoding, errors='ignore') # 解码文件内容
在转换为为utf-8,为啥要用二进制转呢,因为有些字符直接转报错

最后按照 列表从上往下合并

=============================================================

代码 TextMerger.py

一片代码就可以运行 ,代码by 模型自动生成

import tkinter as tk
import os
import chardet
from tkinter import messagebox
import subprocess

import tkinter.ttk as ttk
import tkinter.filedialog
import winreg

# 定义寻找注册表中路径的函数
def find_program(program):
    try:
        registry_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\\" + program + ".exe")
        value, regtype = winreg.QueryValueEx(registry_key, "")
        return value
    except WindowsError:
        return None


class TextMerger:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("文本合并软件")
        # 设置窗口大小
        self.window.geometry("600x600")
        # 获取屏幕尺寸
        screen_width = self.window.winfo_screenwidth()
        screen_height = self.window.winfo_screenheight()

        # 获取窗口实际大小
        window_width = self.window.winfo_width()
        window_height = self.window.winfo_height()

        # 计算窗口左上角位置
        x = (screen_width - window_width) // 2
        y = (screen_height - window_height) // 2

        # 设置窗口左上角位置
        self.window.geometry("+%d+%d" % (x, y))
        self.file_list = []
        self.selected_item = None
        
        # 创建三个容器,分别用于显示文件列表、按钮和操作提示
        self.file_list_container = tk.Frame(self.window)
        self.button_container = tk.Frame(self.window)
        self.operation_prompt_container = tk.Frame(self.window)

        # 创建文件列表显示窗口
        self.file_list_label = tk.Label(self.file_list_container, text="文件列表")
        self.file_list_label.pack(side=tk.TOP, padx=10, pady=10)
        self.file_list_tree = ttk.Treeview(self.file_list_container, columns=('序号', '文件路径', '文件编码'), show='headings',selectmode='extended')
        self.file_list_tree.heading('序号', text='序号')
        self.file_list_tree.heading('文件路径', text='文件路径')
        self.file_list_tree.heading('文件编码', text='文件编码')
        self.file_list_tree.column('序号',minwidth=0,  width=50, anchor='center')
        self.file_list_tree.column('文件路径', width=399, anchor='w')
        self.file_list_tree.column('文件编码', width=100, anchor='center')
        

        self.file_list_tree.config(selectmode="browse")
        self.file_list_tree.bind("<<TreeviewSelect>>", self.on_item_selected)
            # 绑定拖放事件
        self.file_list_tree.bind("<<TreeviewDrop>>", self.on_drag_enter)
        self.file_list_tree.bind("<<TreeviewEndDrag>>", self.on_drop)
       
        # 绑定拖放进入和离开事件
        self.file_list_tree.bind("<<TreeviewDragEnter>>", self.on_drag_enter)
        self.file_list_tree.bind("<<TreeviewDragLeave>>", self.on_drag_leave)

        
        self.file_list_tree.pack(side=tk.TOP, padx=10, pady=10)

        # 创建按钮区
        self.select_dir_button = tk.Button(self.button_container, text="选择目录", command=self.select_directory)
        self.select_dir_button.pack(side=tk.LEFT, padx=10, pady=10)
        self.remove_button = tk.Button(self.button_container, text="移除", command=self.remove_selected_file)
        self.remove_button.pack(side=tk.LEFT, padx=10, pady=10)
        self.up_button = tk.Button(self.button_container, text="上移", command=self.move_file_up)
        self.up_button.pack(side=tk.LEFT, padx=10, pady=10)
        self.down_button = tk.Button(self.button_container, text="下移", command=self.move_file_down)
        self.down_button.pack(side=tk.LEFT, padx=10, pady=10)
        self.merge_button = tk.Button(self.button_container, text="合并文件", command=self.merge_files_confirm)
        self.merge_button.pack(side=tk.LEFT, padx=10, pady=10)
        self.clear_button = tk.Button(self.button_container, text="清空列表", command=self.clear_file_list)
        self.clear_button.pack(side=tk.LEFT, padx=10, pady=10)

        # 创建操作提示窗口
        self.operation_prompt_label = tk.Label(self.operation_prompt_container, text="操作提示")
        self.operation_prompt_label.pack(side=tk.TOP, padx=10, pady=10)
        self.operation_prompt_text = tk.Text(self.operation_prompt_container, height=10, width=80)
        self.operation_prompt_text.pack(side=tk.TOP, padx=10, pady=10)

        # 将三个容器添加到窗口中
        self.file_list_container.pack(side=tk.TOP, padx=10, pady=10)
        self.button_container.pack(side=tk.TOP, padx=10, pady=10)
        self.operation_prompt_container.pack(side=tk.TOP, padx=10, pady=10)
        self.window.mainloop()
    
    def select_directory(self):
        # 打开文件选择对话框,选择一个文件夹
        directory = tk.filedialog.askdirectory()
        if directory:
            # 遍历文件夹下的所有txt文件,并将它们添加到文件列表中
            for root, dirs, files in os.walk(directory):
                for file in files:
                    if file.lower().endswith('.txt'):
                        file_path = os.path.join(root, file)
                        # 获取文件编码
                        with open(file_path, 'rb') as f:
                            encoding = chardet.detect(f.read(10000))['encoding']
                        # 将文件信息添加到文件列表中
                        self.file_list.append({'path': file_path, 'encoding': encoding})
                        self.file_list_tree.insert('', 'end', values=(len(self.file_list), file_path, encoding))
    
    def remove_selected_file(self):
        # 删除选中的文件 
        self.operation_prompt_text.insert('end', "移除列表序号:"+ str(self.selected_item+1) +"\n")
        self.file_list.pop(self.selected_item)
        self.selected_item = None
        self.refresh_file_list()
        

    def move_file_up(self):
        # 将选中的文件往上移一位
        if  self.selected_item > 0:
            self.file_list[self.selected_item], self.file_list[self.selected_item - 1] = self.file_list[self.selected_item - 1], self.file_list[self.selected_item]
            self.selected_item -= 1
            self.refresh_file_list()
    
    def move_file_down(self):
        # 将选中的文件往下移一位
        if  self.selected_item < len(self.file_list) - 1:
            self.file_list[self.selected_item], self.file_list[self.selected_item + 1] = self.file_list[self.selected_item + 1], self.file_list[self.selected_item]
            self.selected_item += 1
            self.refresh_file_list()
    
    
    def merge_files_confirm(self):
        #文件合并
        self.operation_prompt_text.insert('end', "开始合并文件 ...\n" )
        merged_content =''
        for file_info in self.file_list:
            with open(file_info['path'], 'rb') as f:
                content = f.read()
                if len(content)>0 and file_info['encoding'] != 'None':
                    try:
                        self.operation_prompt_text.insert('end', "合并文件 %s\n" % file_info['path'])
                        content = content.decode(file_info['encoding'], errors='ignore') # 解码文件内容
                   
                        if  isinstance(content, bytes):
                            self.operation_prompt_text.insert('end', "文件无法用编码 %s 解码\n" % file_info['path'])
                            continue
                        # 转换为utf-8编码
                        content8 = content.encode("utf-8").decode("utf-8")
                  
                        merged_content = merged_content +str(content8)
                    except:
                        self.operation_prompt_text.insert('end', "文件无法用编码 %s 解码\n" % file_info['path'])
                        continue
                   

        # 写入合并后的文件
        file_name = 'merged.txt'
        file_path = os.path.join(os.getcwd(), file_name)
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(merged_content)
    
        # 提示合并完成
        self.operation_prompt_text.insert('end', "文件合并完成,合并后的文件为 %s\n" % file_path)
        self.operation_prompt_text.insert('end', "打开合并文件 %s\n" % file_path)
         # 从注册表中获取 Notepad++ 的安装路径
        notepad_plus_plus_path = find_program("notepad++")
        if os.path.exists(notepad_plus_plus_path):
            subprocess.Popen([notepad_plus_plus_path, file_path])
        else:
            subprocess.Popen(['notepad.exe', file_path])
        os.startfile(os.getcwd())  # 打开系统文件夹并选中该文件夹
    
    def clear_file_list(self):
        # 清空文件列表
        self.file_list = []
        self.refresh_file_list()
        self.operation_prompt_text.insert('end', "你清空文件列表.\n")
    
    def refresh_file_list(self):
        # 刷新文件列表
        self.file_list_tree.delete(*self.file_list_tree.get_children())
        for i, file_info in enumerate(self.file_list):
            self.file_list_tree.insert('', 'end', values=(i + 1, file_info['path'], file_info['encoding']))
    
    def on_item_selected(self, event):
        
        selected_items = event.widget.selection()
        for item in selected_items:
            index = self.file_list_tree.index(item)
            if index is not None:
                self.selected_item = index
            else:
                self.selected_item = None
        self.operation_prompt_text.insert('end', "选中:"+ str(self.selected_item+1) +"\n")
                

    def on_drag_enter(self, event):
        # 拖动文件夹到窗口时高亮窗口
        self.window.config(background="#aaffaa")
    
    def on_drag_leave(self, event):
        # 拖动文件夹离开窗口时恢复窗口背景色
        self.window.config(background="#ffffff")
    

    
    def on_drop(self, event):
        # 将拖入窗口的文件夹路径添加到文件列表中
        file_path = event.data.strip()
        if os.path.isdir(file_path):
            for root, dirs, files in os.walk(file_path):
                for file in files:
                    if file.lower().endswith('.txt'):
                        file_path = os.path.join(root, file)
                        # 获取文件编码
                        with open(file_path, 'rb') as f:
                            encoding = chardet.detect(f.read())['encoding']
                        # 将文件信息添加到文件列表中
                        self.file_list.append({'path': file_path, 'encoding': encoding})
                        self.refresh_file_list()
            self.window.config(background="#ffffff")
        else:
            self.operation_prompt_text.insert('end', "拖入的不是文件夹\n")
    
    def update_message(self, message):
        self.operation_prompt_text.delete("1.0", "end")
        self.operation_prompt_text.insert("end", message)
        
if __name__ == '__main__':
    TextMerger()

猜你喜欢

转载自blog.csdn.net/u013628121/article/details/129642803
今日推荐