Erlo

用 AI 实现一个 GBK/GB2312 转 UTF-8 工具:轻松解决文本编码转换难题(附完整源码)

2025-04-17 17:30:18 发布   57 浏览  
页面报错/反馈
收藏 点赞

用 AI 实现一个 GBK/GB2312 转 UTF-8 工具:轻松解决文本编码转换难题

在处理历史文件或与不同系统交互时,我们经常会遇到 GBK 或 GB2312 编码的文本文件。虽然现在 UTF-8 是主流,但手动转换这些旧编码文件既繁琐又容易出错。为了解决这个问题,我开发了一个简单的图形界面工具,可以批量将指定文件夹下的 GBK/GB2312 文件转换为 UTF-8 编码。

工具概览

这个工具使用 Python 和 Tkinter 构建,提供了一个直观的用户界面。它具备以下主要功能:

  • 图形界面: 简洁易用,无需命令行操作。
  • 文件夹选择: 方便地选择包含需要转换文件的文件夹。
  • 智能编码检测: 利用 chardet 库自动识别文件编码,并针对 GBK/GB2312 做了优化处理。
  • 批量转换: 递归遍历文件夹,自动处理所有识别出的 GBK/GB2312 文本文件。
  • 跳过机制: 自动跳过已经是 UTF-8 或无法识别编码的文件。
  • 实时日志: 在界面上显示详细的转换过程和结果。
  • 多线程: 转换过程在后台线程进行,避免界面卡顿。

界面截图

file

如何使用

您可以选择以下两种方式之一来使用该工具:

1. 直接运行 (需要 Python 环境)

  • 确保您的电脑已安装 Python 3。
  • 下载或克隆项目代码。
  • 在项目目录下打开终端或命令提示符,安装依赖:
    pip install -r requirements.txt
    
  • 运行主程序:
    python main.py
    
  • 在弹出的窗口中,点击“浏览”选择目标文件夹,然后点击“开始转换”。

2. 使用预编译的可执行文件

  • 访问项目的 GitHub Releases 页面。
  • 下载适用于您操作系统的最新版本(例如 Windows 下载 .exe 文件)。
  • 直接双击运行下载的文件即可。

完整源代码

以下是工具的主要 Python 源代码 (main.py):

import tkinter as tk
from tkinter import filedialog, messagebox, scrolledtext
import os
import chardet
import threading
import webbrowser # ", self.open_link)

        # 配置行列权重,使控件随窗口缩放
        master.grid_rowconfigure(3, weight=1) # 日志区域占满剩余空间
        master.grid_rowconfigure(4, weight=0) # 链接行不扩展
        master.grid_columnconfigure(1, weight=1)

    def log(self, message):
        """向日志区域添加消息"""
        self.log_text.config(state=tk.NORMAL)
        self.log_text.insert(tk.END, message + "n")
        self.log_text.see(tk.END) # 滚动到底部
        self.log_text.config(state=tk.DISABLED)
        self.master.update_idletasks() # 强制更新界面

    def browse_folder(self):
        """打开文件夹选择对话框"""
        folder_selected = filedialog.askdirectory()
        if folder_selected:
            self.folder_path_var.set(folder_selected)
            self.log(f"已选择文件夹: {folder_selected}")

    def is_text_file(self, filename):
        """根据扩展名判断是否可能是文本或代码文件"""
        _, ext = os.path.splitext(filename)
        return ext.lower() in TEXT_FILE_EXTENSIONS

    def detect_encoding(self, file_path):
        """检测文件编码"""
        try:
            with open(file_path, 'rb') as f:
                raw_data = f.read(4096) # 读取一部分数据进行检测
            result = chardet.detect(raw_data)
            encoding = result['encoding']
            confidence = result['confidence']
            # chardet有时会将GBK/GB2312检测为其他编码,增加一些兼容性判断
            if encoding and encoding.lower() in ['gb2312', 'gbk', 'gb18030']:
                 return encoding.lower(), confidence
            # 对于置信度不高的常见误判,也尝试按GBK处理
            if encoding and confidence  {TARGET_ENCODING})")
                return True
            else:
                self.log(f"跳过: {os.path.basename(file_path)} (已经是 {TARGET_ENCODING} 或无需转换)")
                return False

        except Exception as e:
            self.log(f"转换失败: {os.path.basename(file_path)} - {e}")
            return False

    def process_folder(self, folder_path):
        """处理指定文件夹下的所有文件"""
        converted_count = 0
        skipped_count = 0
        error_count = 0
        processed_files = 0

        self.log(f"n开始扫描文件夹: {folder_path}")
        for root, _, files in os.walk(folder_path):
            for filename in files:
                if not self.is_text_file(filename):
                    # self.log(f"忽略非文本文件: {filename}")
                    continue

                file_path = os.path.join(root, filename)
                processed_files += 1
                self.log(f"正在处理: {file_path}")
                
                encoding, confidence = self.detect_encoding(file_path)

                if encoding and encoding.lower() in SUPPORTED_ENCODINGS:
                    self.log(f"检测到 {encoding.upper()} (置信度: {confidence:.2f}): {filename}")
                    if self.convert_file_encoding(file_path, encoding):
                        converted_count += 1
                    else:
                        error_count += 1
                elif encoding:
                    # self.log(f"跳过 (非GBK/GB2312编码: {encoding}): {filename}")
                    skipped_count += 1
                else:
                    # self.log(f"跳过 (无法检测编码): {filename}")
                    skipped_count += 1
                    error_count += 1 # 无法检测也算一种错误
        
        self.log(f"n处理完成。共扫描 {processed_files} 个文本/代码文件。")
        self.log(f"成功转换: {converted_count}")
        self.log(f"跳过文件: {skipped_count}")
        self.log(f"转换/检测失败: {error_count}")
        messagebox.showinfo("完成", f"转换完成!n成功: {converted_count}n跳过: {skipped_count}n失败: {error_count}")
        # 转换完成后重新启用按钮
        self.convert_button.config(state=tk.NORMAL)
        self.browse_button.config(state=tk.NORMAL)

    def start_conversion_thread(self):
        """在单独的线程中开始转换过程,避免GUI卡死"""
        folder_path = self.folder_path_var.get()
        if not folder_path or not os.path.isdir(folder_path):
            messagebox.showerror("错误", "请先选择一个有效的文件夹!")
            return

        # 禁用按钮,防止重复点击
        self.convert_button.config(state=tk.DISABLED)
        self.browse_button.config(state=tk.DISABLED)
        self.log_text.config(state=tk.NORMAL)
        self.log_text.delete('1.0', tk.END) # 清空日志
        self.log_text.config(state=tk.DISABLED)

        # 创建并启动线程
        conversion_thread = threading.Thread(target=self.process_folder, args=(folder_path,), daemon=True)
        conversion_thread.start()

    def open_link(self, event):
        """打开GitHub链接"""
        webbrowser.open_new(self.github_url)

if __name__ == "__main__":
    root = tk.Tk()
    app = EncodingConverterApp(root)
    root.mainloop()

项目地址

如果您对这个工具感兴趣,或者想查看完整的项目代码和构建说明,请访问项目的 GitHub 仓库:

https://github.com/dependon/gbk2utf8

希望这个小工具能对您有所帮助!

本文由博客一文多发平台 OpenWrite 发布!

登录查看全部

参与评论

评论留言

还没有评论留言,赶紧来抢楼吧~~

手机查看

返回顶部

给这篇文章打个标签吧~

棒极了 糟糕透顶 好文章 PHP JAVA JS 小程序 Python SEO MySql 确认