批量把UTF-8 转为UTF-8 BOM的脚本

  • Post author:
  • Post category:所有文章
  • Post comments:0评论
  • Post last modified:2025年2月24日
  • Reading time:1 mins read

UTF-8 和 UTF-8 BOM 有什么区别?

UTF-8 和 UTF-8 BOM 的主要区别

  1. 基本概念
    UTF-8:
    是一种可变长度的字符编码,能够表示 Unicode 标准中的任何字符。
    它采用一至四个字节来表示一个字符,其中 ASCII 字符仅使用一个字节。
    其设计初衷是为了与 ASCII 兼容,同时支持更广泛的字符集。
    UTF-8 BOM:
    是 UTF-8 编码的一个可选变体。
    在文件开头添加了一个字节序标记(Byte Order Mark,BOM),即 EF BB BF 这三个字节。
    BOM 主要用于标识文件的编码格式为 UTF-8,并在一定程度上帮助某些应用程序(如文本编辑器、IDE 等)自动检测文件的编码。
  2. 应用场景
    UTF-8:
    因为没有 BOM,文件的体积会稍微小一些(对于包含大量文件的系统,累计节省的空间可能较为可观)。
    更适合在需要高效传输和存储的场景下使用,例如在服务器和客户端之间传输数据时,可以减少传输数据量,提高传输效率。
    在一些编译器或运行环境中,如 C/C++ 等编程语言的编译器,通常默认支持无 BOM 的 UTF-8 文件。
    UTF-8 BOM:
    能够明确标识文件的编码格式,在某些应用程序或系统中更易被识别和正确解析。
    例如,在 Microsoft Windows 操作系统中,某些版本的记事本或其他应用程序更倾向于使用带 BOM 的 UTF-8 文件来避免编码检测问题。
    在跨平台或跨语言的项目中,带 BOM 的 UTF-8 文件可以减少因编码格式不明确而导致的兼容性问题。
  3. 兼容性问题
    UTF-8:
    由于没有 BOM,某些旧版本的软件或应用程序可能无法自动识别文件的编码格式,从而导致字符乱码等问题。
    需要依赖上下文或额外的编码检测机制来确定文件的编码。
    UTF-8 BOM:
    虽然 BOM 可以帮助大多数现代软件正确识别文件的编码,但在某些特定场景下可能会引起问题:
    在一些依赖文件内容(如脚本文件、配置文件等)且对文件开头字节非常敏感的应用程序中,BOM 可能会被视为无效字符,导致文件无法正常解析或运行。
    例如,某些 Unix/Linux 系统的命令行工具或脚本可能无法正确处理带 BOM 的 UTF-8 文件。
  4. 示例
    无 BOM 的 UTF-8 文件:
    内容直接从文件开头开始,没有任何附加标记:
    Hello, 你好!
    带 BOM 的 UTF-8 文件:
    文件开头包含 EF BB BF 三个字节:
    EF BB BF Hello, 你好!

总结
UTF-8 是一种高效、兼容的编码格式,但需要依赖上下文或额外的编码检测机制。
UTF-8 BOM 通过添加 BOM 标记,提高了文件编码 format 的可识别性,但在某些场景下可能会引入兼容性问题。
在实际应用中,如果需要确保文件的编码格式明确无误地被识别,可以使用 UTF-8 BOM;如果更关注文件的传输效率和兼容性,则可以使用无 BOM 的 UTF-8。(建议根据具体应用场景选择合适的编码格式)

批量把 UTF-8 转 UTF-8 BOM 的脚本

# 使用当前脚本所在路径作为源文件夹和目标文件夹
$sourceFolder = $PSScriptRoot  # 源文件夹路径(当前脚本所在路径)
$destinationFolder = Join-Path -Path $PSScriptRoot -ChildPath "convert_to_utf8bom"  # 目标文件夹路径(当前脚本所在路径下的 convert_to_utf8bom 文件夹)

# 创建目标文件夹(如果不存在)
if (-not (Test-Path -Path $destinationFolder)) {
    New-Item -ItemType Directory -Path $destinationFolder
}

# 遍历源文件夹中的所有文件(包括子文件夹)
Get-ChildItem -Path $sourceFolder -Include *.txt, *.c, *.h -Recurse | ForEach-Object {
    $sourceFilePath = $_.FullName
    $relativePath = $_.FullName.Substring($sourceFolder.Length).TrimStart('\')
    $destinationFilePath = Join-Path -Path $destinationFolder -ChildPath $relativePath

    # 确保目标文件夹存在
    $destinationDirectory = Split-Path -Path $destinationFilePath -Parent
    if (-not (Test-Path -Path $destinationDirectory)) {
        New-Item -ItemType Directory -Path $destinationDirectory
    }

    # 读取文件内容(无签名UTF-8)
    $content = Get-Content -Path $sourceFilePath -Encoding UTF8 -Raw

    # 将内容转换为字节数组(带BOM的UTF-8)
    $bytes = [System.Text.Encoding]::UTF8.GetBytes($content)
    $bom = [System.Text.Encoding]::UTF8.GetPreamble()  # 获取BOM
    $bytesWithBOM = $bom + $bytes

    # 将带BOM的字节数组写入新文件
    Set-Content -Path $destinationFilePath -Value $bytesWithBOM -Encoding Byte
}

发表回复