string - 将 PowerShell(欧洲)中的字符串转换为 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”。
解决方案
PowerShell ISE 似乎在ANSI中编码字符串常量。
这仅适用于与外部程序通信,而您使用的是进程内 .NET API。
顺便说一句:与使用活动OEM代码页的常规控制台窗口的这种差异是导致过时 ISE 出现问题的原因之一 - 请参阅此答案的底部以获取更多信息。
内存中的字符串文字始终是 .NET 字符串,它们是 UTF-16 编码的(由 16 位 Unicode 代码单元组成),能够表示所有Unicode 字符。[1]
Web 服务调用( Invoke-RestMethod
, )中的字符编码Invoke-WebRequest
:
要发送UTF-8 字符串,请指定charset=utf-8
为-ContentType
参数的一部分;例如:
Invoke-RestMethod -ContentType 'text/plain; charset=utf-8' ...
在接收字符串时,PowerShell 会根据响应内容标头中明确指定的字段(字符编码)自动解码它们,或者charset
在没有它的情况下使用 ISO-8859-1(与 Windows-8859-1 密切相关,但实际上是Windows的一个子集) 1252)。
- 如果给定的响应没有指定 a
charset
但实际上使用了与 ISO-8859-1不同的编码 - 比如说 UTF-8 - PowerShell 将误解收到的字符串,这需要事后重新编码- 请参阅此答案。
与外部程序通信时的字符编码:
如果您需要将具有特定编码的字符串发送到外部程序(通过管道,目标程序通过 stdin 接收),请将$OutputEncoding
首选项变量设置为该编码,PowerShell 会自动将您的 .NET 字符串转换为指定的编码.
通过管道将 UTF-8 编码的字符串发送到外部程序:
$OutputEncoding = [System.Text.UTF8Encoding]::new()
但是请注意,仅此一项还不足以正确接收来自外部程序的 UTF-8 输出;为此,您需要设置[Console]::OutputEncoding
为相同的编码。
要使您的 PowerShell 会话完全支持 UTF-8(无论是在 ISE 还是常规控制台窗口中):
# 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()
有关更多信息,请参阅此答案。
[1] 但是请注意,代码点大于 的 Unicode 字符0xFFFF
,即所谓的 BMP(基本多语言平面)之外的字符,必须用两个16 位代码单元 ( [char]
) 表示,即所谓的代理对.
推荐阅读
- java - java多线程运行,当一个线程找到解决方案时停止线程
- javascript - 登录后如何显示用户名
- python - 我将如何检查图像的 Discord 消息?
- javascript - 使用 Javascript Incode LogicApps 调整图像大小
- python - 在矩阵中获得零的非对角镜像元素的最快方法是什么?
- r - R-从多个不同长度的向量制作一个图形
- google-sheets - 如何使用 Google 表格中的过滤功能中的数据创建多列
- python - 在类方法中引发异常的无效语法
- mongodb - 我无法在新的 M1 macbook 中使用 mongod,每次我写它时,终端都会出现一堆代码。解决办法是什么?
- ansible - Ansible 如何根据某些属性选择主机并在运行时使用它们的 ip 地址创建列表