关于 PowerShell 的中文乱码问题

发布时间:2026-06-22 12:58 最后更新:2026-06-22 13:13 浏览量:共 26 次浏览

## PowerShell 处理 UTF-8 中文文件的正确方法
根本问题 :PowerShell 的 Get-Content / Set-Content / -replace 操作默认使用系统区域编码(简体 Windows 是 GBK/CP936)读写文件,即使文件本身是 UTF-8(没有 BOM 的 UTF-8 在 Windows 上尤其容易被错判)。

正确做法——永远用 .NET API 显式指定编码 :

```
# 读取 UTF-8 文件(无论是否带 BOM)
$path = 'E:\AI-HaoPing\V5.1-SaaS-GLM5.2\admin\super\shops.html'
$content = [System.IO.File]::ReadAllText($path, [System.Text.Encoding]::UTF8)

# 执行字符串替换(在内存中的 .NET 字符串里替换,不会乱码)
$oldText = "const result = await fetchData('shop_api.php?action=delete&id=' + id);"
$newText = "const result = await postData('shop_api.php?action=delete&id=' + id,
{}, 'POST');"
if ($content.Contains($oldText)) {
$content = $content.Replace($oldText, $newText)
Write-Host '替换成功'
} else {
Write-Host '未找到目标字符串(可能已替换过)'
}

# 写回 UTF-8(不带 BOM,与标准 HTML 一致)
$utf8NoBom = New-Object System.Text.UTF8Encoding $false
[System.IO.File]::WriteAllText($path, $content, $utf8NoBom)
```
核心规则 :

1. 永远不要用 Get-Content -Raw 或 Set-Content 处理含中文的 UTF-8 文件
2. 永远不要用 -replace 对整文件内容做批量替换(正则 + 编码转换叠加极易出错)
3. 读用 [System.IO.File]::ReadAllText($path, [System.Text.Encoding]::UTF8)
4. 写用 [System.IO.File]::WriteAllText($path, $content, (New-Object System.Text.UTF8Encoding $false))
5. 替换用 .Replace(旧, 新) 方法(字符串字面量匹配,比正则安全得多)
6. 替换前先 Contains 判断是否存在,避免误操作空替换
7. 多个替换在 同一次读-多次替换-一次写 的流程内完成,避免多次 IO 累积编码错误
由于这个项目里的 modify_files.ps1 使用了 Get-Content + -replace , 不要运行它 。我直接用 IDE 的文件编辑工具完成了修改,避免了 PowerShell 编码问题。后续如有批量修改需求,建议按上面 .NET API 方式改写脚本后再运行。

 

 

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

关于 PowerShell 的中文乱码问题 :您说的 GBK→替换→UTF8 思路是对的。但其实有更简单的方法,问题根源在于 PowerShell 的 Get-Content / -replace / Set-Content 默认走系统编码(GBK/CP936),无论文件本身是什么编码。正确的做法是 完全绕过 PowerShell 的编码层 ,直接用 .NET 的 System.IO.File :

```
# 读取:明确指定 UTF-8
$content = [System.IO.File]::ReadAllText($path, [System.Text.Encoding]::UTF8)

# 替换
$content = $content -replace 'old', 'new'

# 写入:明确指定 UTF-8(不带 BOM)
[System.IO.File]::WriteAllText($path, $content, [System.Text.UTF8Encoding]::new
($false))
```
只要严格只用 ReadAllText / WriteAllText ,不用 Get-Content / Set-Content / Out-File ,中文就不会乱。以后如果真需要批量替换,用这个写法就安全。

相关文章

大白MYSQL8。0。36
密码保护:Debian 12.13下如何实现自动备份防黑客方法一例
JVM调优后备份
Debian 12 中文系统 锁定了 locale 配置文件
Mysql 8.0.45配置文件备份
4-5-6文章