问题现象:Excel打开CSV中文全是乱码
用 PowerShell 跑脚本导出 CSV,用 Excel 双击打开,中文全部变成乱码——这是Windows运维人员最常见的问题之一。
根本原因是:PowerShell 5.x 的 Export-Csv 默认使用 UTF-8 without BOM 编码,而 Excel(尤其是中文Windows上的Excel)默认用 GBK(ANSI)打开 CSV 文件,编码不匹配,中文就乱了。
方法一:加 BOM 头(最推荐,兼容 Excel)
UTF-8 with BOM 是 Excel 能正确识别 UTF-8 编码的唯一可靠方式。PowerShell 5.x 的 Export-Csv 默认不带 BOM,需要手动处理:
# PowerShell 5.x 加 BOM 方法
$data | Export-Csv -Path "output.csv" -NoTypeInformation -Encoding UTF8
# 上面这行在 PS 5.1 实际输出的是 UTF-8 without BOM
# 需要手动在文件头写入 BOM 标记
$file = "output.csv"
$data | Export-Csv -Path $file -NoTypeInformation -Encoding UTF8
# 手动添加 BOM
$bytes = [System.IO.File]::ReadAllBytes($file)
$bom = [byte[]] @(0xEF, 0xBB, 0xBF)
$newBytes = New-Object byte[] ($bom.Length + $bytes.Length)
$bom.CopyTo($newBytes, 0)
$bytes.CopyTo($newBytes, $bom.Length)
[System.IO.File]::WriteAllBytes($file, $newBytes)
更简洁的方案(推荐):
# 直接用 StreamWriter 写入 BOM
$file = "output.csv"
$sw = New-Object System.IO.StreamWriter($file, $false, [System.Text.UTF8Encoding]::new($true))
$data | ConvertTo-Csv -NoTypeInformation | ForEach-Object { $sw.WriteLine($_) }
$sw.Close()
方法二:用 Out-File 替代 Export-Csv(最简单)
$data | ConvertTo-Csv -NoTypeInformation | Out-File -FilePath "output.csv" -Encoding utf8BOM
注意:PowerShell 7 支持 -Encoding utf8BOM 参数,PowerShell 5.x 的 Out-File -Encoding UTF8 实际上会写入 BOM(PS 5.x 的 UTF8 默认带 BOM),行为刚好和 Export-Csv 相反。
所以在 PowerShell 5.x 中最简单的写法:
$data | Export-Csv -Path "output.csv" -NoTypeInformation
# 然后手动用 Notepad++ 转换编码为 UTF-8 with BOM
# 或者用下面这行替代
$data | ConvertTo-Csv -NoTypeInformation | Out-File -FilePath "output.csv" -Encoding UTF8
方法三:直接输出 GBK 编码(Excel 打开最省心)
如果目标用户全是中国区、只用 Excel 打开,直接输出 GBK 编码最省事:
$file = "output.csv"
$encoding = [System.Text.Encoding]::GetEncoding("GBK")
$sw = New-Object System.IO.StreamWriter($file, $false, $encoding)
$data | ConvertTo-Csv -NoTypeInformation | ForEach-Object { $sw.WriteLine($_) }
$sw.Close()
优点:Excel 双击打开,中文完美显示,无需任何额外操作。
缺点:非中文系统打开会乱码,不适合国际化场景。
方法四:使用 Import-Excel 模块(完全绕过 CSV 编码问题)
如果可以安装模块,直接用 Import-Excel 输出真正的 .xlsx 文件,彻底摆脱编码问题:
# 安装模块(仅需一次)
Install-Module -Name Import-Excel -Scope CurrentUser -Force
# 导出 Excel 文件(中文完美,无需担心编码)
$data | Export-Excel -Path "output.xlsx" -AutoSize -TableName "Data"
这是最彻底的方案——Excel 原生格式,编码、格式、字体全没问题。
方法五:PowerShell 7 的正确姿势
PowerShell 7 对编码的处理更加规范,Export-Csv 的 -Encoding 参数支持更多选项:
# PowerShell 7 正确写法
$data | Export-Csv -Path "output.csv" -NoTypeInformation -Encoding utf8BOM
PowerShell 7 中 utf8BOM 会写入 BOM,utf8 则不写入 BOM,行为清晰可预期。
如果你的脚本需要在 PS 5.x 和 PS 7 中同时运行,建议用条件判断:
if ($PSVersionTable.PSVersion.Major -ge 7) {
$data | Export-Csv -Path "output.csv" -NoTypeInformation -Encoding utf8BOM
} else {
# PS 5.x: Out-File 的 UTF8 默认带 BOM
$data | ConvertTo-Csv -NoTypeInformation | Out-File -FilePath "output.csv" -Encoding UTF8
}
原理解析:为什么 Export-Csv 会乱码?
这个坑的根源在于 Windows 的编码历史:
- PowerShell 5.x Export-Csv -Encoding UTF8:输出 UTF-8 without BOM
- PowerShell 5.x Out-File -Encoding UTF8:输出 UTF-8 with BOM(和 Export-Csv 相反!)
- Excel(中文Windows):默认用 ANSI(GBK)打开 CSV,没有 BOM 就识别不出 UTF-8
- PowerShell 7 Export-Csv -Encoding utf8:输出 UTF-8 without BOM(和 PS 5 行为一致)
- PowerShell 7 Export-Csv -Encoding utf8BOM:输出 UTF-8 with BOM(显式指定)
所以最稳妥的方案是:用 Out-File 替代 Export-Csv 来输出 CSV,或者在 PS 7 中显式指定 -Encoding utf8BOM。
总结:该用哪种方法?
| 场景 | 推荐方法 |
|---|---|
| 需要 Excel 直接打开,中文Windows | 方法三(GBK编码)或方法一(UTF-8 with BOM) |
| 跨平台,需要 UTF-8 | 方法一(StreamWriter + BOM) |
| 可以安装模块,追求最佳体验 | 方法四(Import-Excel 输出 xlsx) |
| 已升级 PowerShell 7 | 方法五(-Encoding utf8BOM) |
相关问题推荐阅读:
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论