GBK转UTF\-8编码自动转换工具 使用文档

GBK转UTF-8编码自动转换工具 使用文档

1. 文档概述

1.1 工具简介

本Python脚本为嵌入式工程专用编码批量转换工具,专门解决STM32等单片机工程中,Keil MDK默认GBK编码代码文件,与VSCode、CubeIDE、Linux编译环境UTF-8编码不兼容导致的中文乱码、编译报错、注释异常问题。

脚本全自动遍历工程内所有.c/.h源码文件,自动识别文件编码,将GBK编码文件无损转为带BOM的UTF-8编码(utf-8-sig),适配Keil、VSCode、CubeIDE全平台打开无乱码。

1.2 适用场景

  • Keil MDK工程默认GBK中文注释,VSCode打开乱码

  • 跨平台协作:Windows Keil工程迁移至Linux/GCC编译报错

  • 批量统一整个源码工程编码格式,避免混合编码引发编译异常

  • 无需手动逐个修改文件,一键批量转换,保留全部代码逻辑与注释

1.3 运行环境

  • Python版本:Python3.6及以上(推荐Python3.9/3.10)

  • 运行系统:Windows10/11、Linux、MacOS全平台兼容

  • 依赖库:无需额外安装第三方库,仅使用Python内置标准库,开箱即用


2. 工具核心功能说明

  1. 全自动递归遍历:自动扫描脚本所在根目录及所有子文件夹,匹配全部.c、.h源码文件

  2. 智能编码识别:自动判断文件是否为UTF-8编码,已适配文件直接跳过,不重复转换

  3. 安全转换机制:转换前先生成临时备份文件,转换成功后再删除备份,避免断电/中断导致源码损坏

  4. 输出UTF-8带BOM:输出utf-8-sig格式,完美兼容Keil MDK(Keil原生不支持无BOM UTF-8)

  5. 清晰日志输出:实时打印文件总数、各类型文件数量、转换成功文件路径、最终统计结果

  6. 异常容错:非GBK/非UTF-8未知编码文件,自动跳过,不破坏原始代码


3. 工具工作原理(核心流程)

  1. 步骤1:路径遍历:获取脚本所在根目录,递归检索所有后缀为.c/.h的源码文件

  2. 步骤2:原生字节读取:以二进制模式读取文件原始字节,避免编码前置解析报错

  3. UTF-8预检测:尝试用UTF-8解码,解码成功说明本身为UTF-8,直接跳过

  4. GBK解码转换:UTF-8解码失败后,尝试GBK解码,匹配Keil默认源码编码

  5. 临时备份防护:生成.gbktmp临时备份文件,防止转换过程中断导致源码丢失

  6. 编码重写:删除原GBK文件,新建同名文件,以UTF-8-SIG(带BOM)格式写入源码内容

  7. 清理备份:转换无误后自动删除临时备份文件,完成单文件转换

  8. 结果统计:最终输出已转换文件数、跳过文件数,方便核对工程整体编码情况


4. 详细使用步骤

4.1 文件放置要求

必须将 gbk2utf8.py 脚本直接放到【工程根目录】,和CORE、USER、HARDWARE等源码总文件夹同级,脚本会自动递归扫描全部子目录。

4.2 运行方式(两种任选)

方式一:CMD/终端命令行运行(推荐)
  1. 打开CMD或者PowerShell,cd切换至工程根目录

  2. 输入运行命令:python gbk2utf8.py

  3. 等待脚本自动执行,查看终端打印日志即可

方式二:直接双击运行

Windows系统可直接双击py脚本文件运行,适合新手极简操作。

4.3 运行日志示例

plaintext 复制代码
脚本目录: D:\STM32H7_Project
搜索到文件总数: 126
  .c: 72 个
  .h: 54 个

  [OK] USER\main.c
  [OK] HARDWARE\led.c
  [OK] HARDWARE\uart.c

完成: 36 个已转换, 90 个已是 UTF-8 跳过

5. 关键特性说明(嵌入式开发重点)

5.1 为什么必须输出 UTF-8-SIG(带BOM)?

Keil MDK编译器不支持无BOM的标准UTF-8文件,打开依然中文乱码;加入BOM头的UTF-8-SIG文件,可以同时兼容:Keil MDK、VSCode、CubeIDE、GCC编译器,全平台中文注释无乱码。

5.2 安全备份机制说明

脚本不会直接覆盖原文件,流程为:原文件备份→删除原文件→新建UTF8文件→删除备份。极端情况下程序中断,依然保留.gbktmp备份文件,可手动恢复源码,零丢码风险

5.3 不会破坏代码逻辑

仅修改文件编码格式,不会改动任何一行代码、注释、空格、换行符,编译效果和原工程完全一致,无编译报错风险。


6. 注意事项

  1. 运行前建议整体工程备份一次:虽然脚本自带临时备份,工程整体备份可双重兜底

  2. 请勿在代码编译、Keil打开工程时运行脚本:文件被软件占用会导致转换失败

  3. 仅支持.c/.h源码文件:不会修改hex、axf、uvprojx工程配置文件,不影响工程配置

  4. 混合编码工程建议一次性转换完成:避免工程内部同时存在GBK和UTF-8文件,依旧出现乱码

  5. 不要修改脚本后缀匹配规则:修改EXTS会导致误转换其他格式文件


7. 常见问题与故障排查

Q1:运行提示 python 不是内部或外部命令?

原因:电脑未安装Python,或Python未添加系统环境变量。解决:安装Python3并勾选Add to PATH,重启终端再次运行。

Q2:提示未找到任何.c/.h文件?

原因:脚本没有放在工程根目录,放在了子文件夹内。解决:移动脚本到USER、HARDWARE同级的根目录。

Q3:部分文件依旧中文乱码?

原因:文件既不是GBK也不是标准UTF-8(比如ANSI、GB2312)。解决:极少数特殊编码文件手动用VSCode打开,右下角手动切换编码即可。

Q4:转换后Keil打开依旧乱码?

检查Keil编辑器编码设置:Edit→Configuration→Editor,将编码设置为UTF-8,重启Keil即可。


8. 脚本源码

python 复制代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
GBK -> UTF-8 转换工具
用法: python gbk2utf8.py   (放在工程根目录运行)
"""
import os
import glob

BASE = os.path.dirname(os.path.abspath(__file__))
EXTS = ('.c', '.h')

def main():
    all_files = []
    for ext in EXTS:
        all_files.extend(glob.glob(os.path.join(BASE, '**', '*' + ext), recursive=True))

    # 调试:打印搜索情况
    print(f'脚本目录: {BASE}')
    print(f'搜索到文件总数: {len(all_files)}')
    for ext in EXTS:
        count = sum(1 for f in all_files if f.endswith(ext))
        print(f'  {ext}: {count} 个')

    if not all_files:
        print('\n未找到任何 .c/.h 文件,请确认脚本是否放在工程根目录。')
        return

    converted = 0
    skipped = 0

    for fpath in sorted(all_files):
        # 1. 读取原始字节
        with open(fpath, 'rb') as f:
            data = f.read()

        # 2. 已是 UTF-8,跳过
        try:
            data.decode('utf-8')
            skipped += 1
            continue
        except UnicodeDecodeError:
            pass

        # 3. GBK 解码
        try:
            text = data.decode('gbk')
        except Exception:
            skipped += 1
            continue

        # 4. 复制副本
        tmp = fpath + '.gbktmp'
        with open(tmp, 'wb') as f:
            f.write(data)

        # 5. 删除原文件
        os.remove(fpath)

        # 6. 读副本(GBK) → 新建同名文件(UTF-8+BOM)
        with open(tmp, 'r', encoding='gbk') as fin:
            text = fin.read()
        with open(fpath, 'w', encoding='utf-8-sig') as fout:
            fout.write(text)

        # 7. 删除副本
        os.remove(tmp)

        rel = os.path.relpath(fpath, BASE)
        print(f'  [OK] {rel}')
        converted += 1

    print(f'\n完成: {converted} 个已转换, {skipped} 个已是 UTF-8 跳过')

if __name__ == '__main__':
    main()

相关推荐
数量技术宅2 小时前
2026量化前沿:从Reddit热帖到Python实战,如何用赫斯特指数(Hurst)狙击虚假突破?
开发语言·python
华如锦2 小时前
面了很多 Java转AI Agent方向,一些面试题总结
java·开发语言·人工智能·python·ai
戴西软件2 小时前
戴西 DLM 许可授权管理系统:破解无网络环境下工业软件授权难题,助力制造企业降本增效
网络·人工智能·python·深度学习·程序人生·算法·制造
Dxy12393102162 小时前
Python线程锁:为什么多线程会“打架“,以及怎么解决
开发语言·前端·python
小白学大数据2 小时前
线上故障急救:依托 OpenClaw 日志排查 403 和 503 问题
爬虫·python·selenium·数据分析
databook3 小时前
用SymPy自动因式分解:从面积拼图到代数恒等式
python·数学·动效
艳阳天_.3 小时前
星瀚弹框页面实现
java·前端·python
kernelcraft3 小时前
Boto3:Python 操作 AWS 的官方 SDK
开发语言·python·其他·aws
D3bugRealm3 小时前
cryptography:Python 开发者的加密标准库
开发语言·python·其他