gpt4 book ai didi

powershell - PowerShell Core无法识别unicode

转载 作者:行者123 更新时间:2023-12-03 01:02:21 25 4
gpt4 key购买 nike

我有一个简单的PowerShell Core脚本:

$Message = [IO.File]::ReadAllText("$PSScriptRoot\русский.txt", [System.Text.Encoding]::Default)
$Message

据我所知,PowerShell Core默认为UTF-8。但是,正如您在输出中看到的那样,就Unicode字符而言,它实际上担心比PowerShell 5.1更糟糕。

相同的脚本在PowerShell 5.1上运行良好

Output

将“ReadAllText”更改为
$Message = [IO.File]::ReadAllText("$PSScriptRoot\русский.txt")

什么都不会改变(它不应该改变,因为它是读取操作的编码,但是要清楚一点:))。

最佳答案

文件不包含字符,它们包含字节。要从字节中获取字符,您需要应用一些编码。如果将不同的编码应用于相同的字节,则结果中将获得不同的字符。

以您的字节字符串为例:

PS> $ByteArray = [Byte[]]('24-4D-65-73-73-61-67-65-20-3D-20-5B-49-4F-2E-46-69-6C-65-5D-3A-3A-52-65-61-64-41-6C-6C-54-65-78-74-28-22-24-50-53-53-63-72-69-70-74-52-6F-6F-74-5C-F0-F3-F1-F1-EA-E8-E9-2E-74-78-74-22-2C-20-5B-53-79-73-74-65-6D-2E-54-65-78-74-2E-45-6E-63-6F-64-69-6E-67-5D-3A-3A-44-65-66-61-75-6C-74-29-0D-0A-24-4D-65-73-73-61-67-65' -split '-' | % { [Byte]::Parse($_, 'HexNumber') })
PS> [Text.Encoding]::UTF8.GetString($ByteArray)
$Message = [IO.File]::ReadAllText("$PSScriptRoot\�������.txt", [System.Text.Encoding]::Default)
$Message
PS> [Text.Encoding]::GetEncoding(1251).GetString($ByteArray)
$Message = [IO.File]::ReadAllText("$PSScriptRoot\русский.txt", [System.Text.Encoding]::Default)
$Message
PS> [Text.Encoding]::GetEncoding(1252).GetString($ByteArray)
$Message = [IO.File]::ReadAllText("$PSScriptRoot\ðóññêèé.txt", [System.Text.Encoding]::Default)
$Message

读取文件时使用正确的编码很重要。需要注意的一件事是,脚本文件使用代码页1251,而不是UTF-8。另请注意,根据UTF-8,字节序列 F0-F3-F1-F1-EA-E8-E9(代表代码页1251中的世界 русский)是无效的字节序列,因此,您将获得七个替换字符( U+FFFD)。

由于PowerShell Core默认情况下使用UTF-8,并且您的脚本文件没有BOM来指示(尽管没有BOM可使PowerShell识别代码页1251),因此PowerShell Core使用UTF-8编码读取文件,因此尝试访问 �������.txt(您没有),而不是 русский.txt

如果您将脚本更改为写入文件而不是读取文件,则可以轻松地自己观察它。
PS> $ByteArray2 = [Byte[]](91, 73, 79, 46, 70, 105, 108, 101, 93, 58, 58, 87, 114, 105, 116, 101, 65, 108, 108, 84, 101, 120, 116, 40, 34, 36, 80, 83, 83, 99, 114, 105, 112, 116, 82, 111, 111, 116, 92, 240, 243, 241, 241, 234, 232, 233, 46, 116, 120, 116, 34, 44, 32, 91, 68, 97, 116, 101, 84, 105, 109, 101, 93, 58, 58, 85, 116, 99, 78, 111, 119, 41)
PS> # Representing `[IO.File]::WriteAllText("$PSScriptRoot\русский.txt", [DateTime]::UtcNow)` in codepage 1251
PS> [IO.File]::WriteAllBytes("$(Convert-Path .)\write.ps1", $ByteArray2)
PS> .\write.ps1

现在,您可以使用原始脚本读回文件:
PS> [IO.File]::WriteAllBytes("$(Convert-Path .)\asd.ps1", $ByteArray)
PS> .\asd.ps1
01/18/2019 17:13:15

使用PowerShell Core调用两个脚本:
PS> pwsh -Command ".\write.ps1; .\asd.ps1"
01/18/2019 17:21:02

如您所见,您的脚本已在PowerShell Core中成功执行。如果浏览当前目录,则可以看到它同时包含 русский.txt�������.txt并且它们的内容匹配,这是在控制台上打印的。

实际上,该问题与读写文件无关(脚本文件本身除外)。它可以通过简单的脚本演示,该脚本仅打印字符串文字的字符代码:
PS> $ByteArray3 = [Byte[]](40, 39, 240, 243, 241, 241, 234, 232, 233, 39, 46, 71, 101, 116, 69, 110, 117, 109, 101, 114, 97, 116, 111, 114, 40, 41, 32, 124, 32, 37, 32, 84, 111, 73, 110, 116, 51, 50, 32, 36, 110, 117, 108, 108, 32, 124, 32, 37, 32, 84, 111, 83, 116, 114, 105, 110, 103, 32, 88, 52, 41, 32, 45, 106, 111, 105, 110, 32, 39, 45, 39)
PS> # Representing `('русский'.GetEnumerator() | % ToInt32 $null | % ToString X4) -join '-'` in codepage 1251
PS> [IO.File]::WriteAllBytes("$(Convert-Path .)\test.ps1", $ByteArray3)

在Windows PowerShell中调用它会产生一个结果:
PS> .\test.ps1
0440-0443-0441-0441-043A-0438-0439

虽然PowerShell Core将产生不同的结果:
PS> pwsh -Command ".\test.ps1"
FFFD-FFFD-FFFD-FFFD-FFFD-FFFD-FFFD

解决此问题的一种方法是将UTF-8与BOM一起使用,以确保Windows PowerShell和PowerShell Core在读取脚本文件时将使用相同的编码。

答案是在 [Text.Encoding]::Default.CodePage返回1251的情况下写的,就像在OP中那样。

关于powershell - PowerShell Core无法识别unicode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54215599/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com