Mathias R. Jessen在对该问题的评论中提供了关键指针:
在您的情况下,是Import-Csv
呼叫而不是Export-Csv
导致问题的原因:
为了正确处理使用系统的活动“ANSI”遗留代码页编码的文本文件,Export-Csv
也Import-Csv
需要传递-Encoding Default
, 这是一种 8 位单字节字符编码,例如 Windows-1252。
在Windows PowerShell中,尽管通用文本文件处理Get-Content
/ Set-Content
cmdlet 对默认为Default
编码(顾名思义),但令人遗憾且令人惊讶的是,Import-Csv
并Export-Csv
没有。
请注意,仅在输入文件没有 BOM(字节顺序标记,也称为 Unicode 签名,文件开头的一个魔术字节序列,明确标识文件的编码)时才假定读取默认编码。
不仅有Import-Csv
并且Export-Csv
有不同于Get-Content
/的默认值Set-Content
,它们各自有不同的默认值:
Import-Csv
默认为 UTF-8。
Export-Csv
默认为 ASCII(!),这意味着任何非 ASCII 字符 - 例如ä
, ö
, ü
- 都被音译为文字 ?
字符。导致数据丢失。
相比之下,在PowerShell Core(基于 .NET Core 构建的跨平台版本)中,默认编码是(BOM-less)UTF-8,在所有 cmdlet 中始终如一,这大大简化了事情,并且更容易确定何时确实需要使用-Encoding
参数。
演示 Windows PowerShell Import-Csv
/Export-Csv
行为
Import-Csv
- 默认为UTF-8:
# Sample CSV content.
$str = @'
Column1
aäöü
'@
# Write sample CSV file 't.csv' using UTF-8 encoding *without a BOM*
# (Note that this cannot be done with standard PowerShell cmdlets.)
$null = new-item -type file t.csv -Force
[io.file]::WriteAllLines((Convert-Path t.csv), $str)
# Use Import-Csv to read the file, which correctly preserves the UTF-8-encoded
# umlauts
Import-Csv .\t.csv
以上产生:
Column1
-------
aäöü
如您所见,变音符号被正确保存。
相比之下,如果文件被“ANSI”编码($str | Set-Content t.csv
;-Encoding Default
隐含),变音符号就会被破坏。
Export-Csv
- 默认为ASCII - 数据丢失风险:
基于上面的例子:
Import-Csv .\t.csv | Export-Csv .\t.new.csv
Get-Content .\t.new.csv
产量:
"Column1"
"a???"
如您所见,变音符号被文字问号( ?
) 取代。