问题是什么
PowerShell 的文本编码是中文乱码的高发区:Windows PowerShell 5.1 与 PowerShell 7 的默认行为不同,5.1 用 -Encoding UTF8 写出的文件带 BOM,Out-File 默认写成 UTF-16LE。跨工具交换文本时最稳妥的做法是读写两端都显式指定编码,并确认目标程序是否接受 BOM。
怎么判断实际编码
判断编码最可靠的方式是看字节头:EF BB BF 是 UTF-8 BOM,FF FE 是 UTF-16LE,FE FF 是 UTF-16BE。没有 BOM 且含非 ASCII 字符的文本,无法从内容直接区分 GBK 与 UTF-8,需要分别用两种编码读一次、看哪种显示正常。怀疑乱码时先用 Format-Hex 看前几个字节再决定读法。
基本信息
| 适用平台 | Windows PowerShell 5.1 与 PowerShell 7.x,默认行为有差异 |
|---|---|
| 常见现象 | Get-Content 读到乱码;导出的 CSV 在 Excel 中乱码 |
| 对策 | 读写统一显式 -Encoding;给 Excel 用带 BOM 的 UTF8;纯脚本消费用 UTF8NoBOM |
| 相关变量 | $OutputEncoding 控制管道输出编码;[Console]::OutputEncoding 控制控制台 |
典型使用场景
- 生成的 CSV 用 Excel 打开乱码,需要带 BOM 的 UTF8
- 脚本读取中文配置文件出现乱码,先确认文件的实际编码
- 向 git、python 等外部程序传管道数据时中文变问号
- 批量转换文件编码:按指定编码读入再写出
- 日志采集链路出现乱码,需要统一各环节的编码设置
常用示例
常用示例
Get-Content D:\a.txt -Encoding Default # 5.1 按系统 ANSI 代码页读取(中文系统为 GBK)
Get-Content D:\a.txt -Encoding UTF8 # 按 UTF-8 读取,带 BOM 时自动识别
Set-Content D:\b.txt '中文内容' -Encoding UTF8 # 5.1 写出带 BOM,PowerShell 7 默认无 BOM
$OutputEncoding = [Text.Encoding]::UTF8 # 影响管道传给外部程序时的编码
# 5.1 下写出无 BOM 的 UTF-8
[IO.File]::WriteAllText('D:\c.txt', '中文内容', (New-Object Text.UTF8Encoding($false)))场景与编码选择
| 场景 | 推荐编码 | 说明 |
|---|---|---|
| Excel 打开 CSV | UTF-8 带 BOM | Excel 靠 BOM 判断编码,无 BOM 会按 ANSI 解析 |
| 脚本之间互相消费 | UTF-8 无 BOM | 避免 BOM 混进首行内容 |
| 5.1 的 Out-File 默认 | UTF-16LE | 与其他工具交换时最容易踩坑 |
| 管道传给外部程序 | 由 $OutputEncoding 决定 | 未设置时非 ASCII 字符可能变问号 |
| 读未知编码文件 | 先试 UTF8 再试 Default | 看字节头判断更可靠 |
5.1 的 -Encoding UTF8 会写入 BOM,PowerShell 7 的同名参数默认不写;同名参数默认值不同,是跨版本脚本乱码的常见根源。
同一文件在不同工具下读出两种结果,多半是 BOM 或代码页差异。先看文件头几个字节:EF BB BF 是 UTF-8 BOM,FF FE 是 UTF-16LE。