根本原因:每个命令的默认编码都不同
在 Windows PowerShell 5.1 中,Get-Content 把没有 BOM 的文件按 ANSI 读取,在简体中文 Windows 上就是 GBK(代码页 936);Out-File 和 > 写出 UTF-16;Set-Content 写出 GBK;Export-Csv 默认用 ASCII,中文全部变成 ?。PowerShell 7 统一改成了不带 BOM 的 UTF-8。
乱码
濮撳悕,閮ㄩ棬,鍩庡競 寮犱紵,甯傚満,涓婃捣 鏉庡,閲囪喘,娣卞湷
修复后
姓名,部门,城市 张伟,市场,上海 李娜,采购,深圳
正确读写文件
Get-Content data.csv -Encoding UTF8:没有 BOM 的 UTF-8 文件也能正确读取。Set-Content、Out-File、Add-Content加上-Encoding UTF8写出 UTF-8,在 5.1 中总是带 BOM。Export-Csv data.csv -Encoding UTF8 -NoTypeInformation:避免默认的 ASCII 把中文换成?。- 要给只认 GBK 的旧系统写文件时,在 5.1 中用
-Encoding Default,即系统的 ANSI 编码。 - 一次设置所有命令:在脚本开头写
$PSDefaultParameterValues['*:Encoding'] = 'utf8'。
脚本里的中文变成乱码或报错
.ps1 脚本保存为不带 BOM 的 UTF-8 时,Windows PowerShell 5.1 会按 GBK 读取它。Write-Host "你好" 会输出 浣犲ソ;有时 GBK 还会把引号“吞”进一个乱码字里,导致字符串缺少终止符之类的语法错误。把脚本保存为带 BOM 的 UTF-8 就能解决:VS Code 中点击状态栏右下角的编码,Notepad++ 中在 编码 菜单里选择 UTF-8-BOM。
Invoke-WebRequest 和 Invoke-RestMethod
如果服务器的 Content-Type 中没有写明字符集,Windows PowerShell 5.1 会按 ISO-8859-1 解码响应,UTF-8 的中文就变成 ä½ å¥½。解决办法是取出原始字节自己解码,例如 [Text.Encoding]::UTF8.GetString((Invoke-WebRequest $url).RawContentStream.ToArray())。
控制台显示乱码
如果只是控制台窗口显示乱码,文件本身往往没有问题。用 [Console]::OutputEncoding = [Text.Encoding]::UTF8 切换输出编码;输出要通过管道传给外部程序时,再设置 $OutputEncoding = [Text.Encoding]::UTF8。cmd 中常用的 chcp 65001 作用类似。
Windows 的区域设置中还有一个使用 Unicode UTF-8 提供全球语言支持的 Beta 选项,会把系统的 ANSI 编码改为 UTF-8。它能减少这类乱码,但一些只认 GBK 的旧软件反而可能出现乱码,开启前请先测试。
文件已经写坏了?把它拖到上面的框中,Mojibuster 会修复 浣犲ソ 这类乱码,并把 GBK 文件转换为 UTF-8(参见 GBK 转 UTF-8)。如果文件里已经是 ?,文字就丢失了,只能重新导出。
常见问题
怎么查看 PowerShell 的版本?
执行 $PSVersionTable.PSVersion。5.1 是 Windows 自带的 Windows PowerShell;从 7 开始叫 PowerShell,默认使用 UTF-8。
PowerShell 导出的 CSV 用 Excel 打开为什么是乱码?
PowerShell 7 写出的是不带 BOM 的 UTF-8,中文版 Excel 会按 GBK 打开。请使用 -Encoding utf8BOM,或在 Mojibuster 中保存时添加 BOM。详见 Excel 打开 CSV 乱码。
一定要执行 chcp 65001 吗?
只有跟随控制台代码页的外部程序才需要。在 PowerShell 内部,设置 [Console]::OutputEncoding 就够了。