将 PowerShell(在欧洲)中的字符串转换为 UTF-8

Convert a string in PowerShell (in Europe) to UTF-8

对于 REST 调用,我需要使用

从访问数据库中读取的 UTF-8 格式的德语“Stück”
$conn = New-Object System.Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=$filename;Persist Security Info=False;")

并尝试转换它。 我发现 PowerShell ISE 似乎以 ANSI 编码字符串常量。 所以我尝试在没有数据库的情况下进行最低限度的测试并得到相同的结果:

$Text1 = "Stück" # entered via ISE, this is also what I get from the database
# ($StringFromDatabase -eq $Test1) shows $true

$enc = [System.Text.Encoding]::GetEncoding(1252).GetBytes($Text1)
# also tried [System.Text.Encoding]::GetEncoding("ISO-8859-1") # = 28591

$Text1 = [System.Text.Encoding]::UTF8.GetString($enc)

$Text1
$Text1 = "Stück" # = UTF-8, entered here with Notepad++, encoding set to UTF-8
"must see: $Text1"

所以我得到两个输出 - 转换后的输出(显示“St?ck”)但我需要看到“Stück”。

that PowerShell ISE seems to encode string constants in ANSI.

仅在与 外部程序 通信时适用,而您使用的是 in-process .NET API。

顺便说一句:这种与使用活动 OEM 代码页的常规控制台 windows 的差异是导致过时的 ISE 有问题 - 请参阅 this answer 的底部部分了解更多信息。

字符串文字在内存中总是.NET字符串,它们是UTF-16编码的(由16位Unicode代码单元组成),能够表示所有个Unicode字符.[1]


字符编码在 web-service 调用 (Invoke-RestMethod, Invoke-WebRequest):

发送 UTF-8字符串,指定charset=utf-8作为-ContentType参数的一部分;例如:

Invoke-RestMethod -ContentType 'text/plain; charset=utf-8' ...

接收 字符串时,PowerShell 会根据响应内容 header 中明确指定的 charset 字段(字符编码)自动解码它们,或者,在没有使用 ISO-8859-1 的情况下(它与 Windows-1252 的 子集 密切相关,但实际上是一个 子集

  • 如果给定的响应未指定 charset 但实际上使用了来自 ISO-8859-1 的 不同的 编码 - 比如 UTF-8 - PowerShell 将误解了 收到的字符串,事后需要 re-encoding - 参见 this answer.

外部程序通信时的字符编码:

如果您需要将具有特定编码的字符串发送到外部程序(通过目标程序通过标准输入接收的管道),请将 $OutputEncoding preference variable 设置为该编码,PowerShell 将自动转换您的 .NET 字符串到指定的编码。

通过管道将 UTF-8 编码的字符串发送到外部程序:

$OutputEncoding = [System.Text.UTF8Encoding]::new()

但是请注意,仅此一项不足以正确接收 来自外部程序的 UTF-8 输出;为此,您需要将 [Console]::OutputEncoding 设置为相同的编码。

要使您的 PowerShell session 完全支持 UTF-8(无论是在 ISE 中还是在常规控制台中 window):

# Needed in the ISE only:
chcp >$null # Dummy console-program call that ensures that a console is allocated.

# Set all encodings relevant to communicating with external programs to UTF-8.
$OutputEncoding = [Console]::InputEncoding = [Console]::OutputEncoding =
  [System.Text.UTF8Encoding]::new()

有关详细信息,请参阅 this answer


[1] 但是请注意,代码点大于 0xFFFF 的 Unicode 字符,即 so-called BMP(基本多语言平面)之外的字符,必须是用两个个16位编码单元([char])表示,即so-called代理对.