如何将cyrillic转换为utf16



tl;dr有没有办法将存储在hashtable中的cyrillic转换为UTF-16?将кириллица类似于u043au0438u0440u0438u043bu043bu0438u0446u0430

我需要导入文件,将其解析为idvalue,然后将其转换为.json,现在我正在努力寻找将value转换为utf代码的方法。

是的,需要这样

cyrillic.txt:

1 кириллица

PH:

clear-host
foreach ($line in (Get-Content C:UsersusersDownloadscyrillic.txt)){
$nline = $line.Split(' ', 2)
$properties = @{
'id'= $nline[0] #stores "1" from file
'value'=$nline[1] #stores "кириллица" from file
}
$temp+=New-Object PSObject -Property $properties
}
$temp | ConvertTo-Json | Out-File "C:UsersuserDownloadsdata.json"

输出:

[
{
"id":  "1",
"value":  "кириллица"
},
]

需要:

[
{
"id":  "1",
"value":  "u043au0438u0440u0438u043bu043bu0438u0446u0430"
},
]

在这一点上,作为PH的新手,我甚至不知道如何正确地搜索

基于Jeroen Mostert的有用评论,假设输入文件不包含NUL字符(这通常是text文件的安全假设(,以下操作稳健:

# Sample value pair; loop over file lines omitted for brevity.
$nline = '1 кириллица'.Split(' ', 2)
$properties = [ordered] @{
id = $nline[0]
# Insert aux. NUL characters before the 4-digit hex representations of each
# code unit, to be removed later.
value = -join ([uint16[]] [char[]] $nline[1]).ForEach({ "`0{0:x4}" -f $_ })
}
# Convert to JSON, then remove the escaped representations of the aux. NUL chars.,
# resulting in proper JSON escape sequences.
# Note: ... | Out-File ... omitted.
(ConvertTo-Json @($properties)) -replace '\u0000', 'u'

输出(管道至ConvertFrom-Json以验证其工作(:

[
{
"id": "1",
"value": "u043au0438u0440u0438u043bu043bu0438u0446u0430"
}
]

说明:

  • [uint16[]] [char[]] $nline[1]将存储在$nline[1]中的字符串的[char]实例转换为底层UTF-16代码单元(.NET[char]是编码Unicode代码点的无符号16位整数(。

    • 请注意,这甚至适用于代码点在0xFFFF以上的Unicode字符,即太大而无法放入[uint16]。在所谓的BMP(基本多语言平面(之外的这些字符,例如👍,被简单地表示为UTF-16代码单元的,即所谓的proxy对JSON处理器应该识别(ConvertFrom-Json识别(
    • 但是,在Windows上,会出现这样的字符。可能无法正确渲染,具体取决于控制台窗口的字体。最安全的选择是使用Windows终端,可在Microsoft商店中获得
  • .ForEach()数组方法的调用处理每个生成的代码单元:

    • "`0{0:x4}" -f $_使用可扩展字符串创建一个以NUL字符("`0"(开头、后跟4位十六进制的字符串。手头代码单元的表示(x4(,通过格式运算符-f创建。

      • 需要将最终应该是逐字u前缀的东西临时替换为NUL字符,因为嵌入字符串值中的逐字在其JSON表示中总是被加倍的,因为充当JSON中的转义符
    • 结果类似于"<NUL>043a"ConvertTo-Json对其进行如下转换,因为它必须将每个NUL字符转义为u0000:

      "u0000043a"
      
  • 然后,只需将u0000(转义为\u0000,用于基于正则表达式的-replace操作器(替换为u,即可将ConvertTo-Json的结果转换为所需的转义序列,例如:

    "u0000043a" -replace '\u0000', 'u' # -> "u043a", i.e. к
    

这里有一种方法,只需将其保存到utf16be文件中,然后读取字节并对其进行格式化,跳过前两个字节,即bom(\ueff(。$_它自己不起作用。请注意,有两个utf16编码,它们具有不同的字节顺序,大端序和小端序。cyrillic的范围是U+0400.U+04FF。添加了-nonewline。

'кириллица' | set-content utf16be.txt -encoding BigEndianUnicode -nonewline
$list = get-content utf16be.txt -Encoding Byte -readcount 2 | 
% { 'u{0:x2}{1:x2}' -f $_[0],$_[1] } | select -skip 1
-join $list
u043au0438u0440u0438u043bu043bu0438u0446u0430

必须有一种更简单的方法来做到这一点,但这可能对您有效:

$temp = foreach ($line in (Get-Content -Path 'C:UsersusersDownloadscyrillic.txt')){
$nline = $line.Split(' ', 2)
# output an object straight away so it gets collected in variable $temp
[PsCustomObject]@{
id    = $nline[0]   #stores "1" from file
value = (([system.Text.Encoding]::BigEndianUnicode.GetBytes($nline[1]) | 
ForEach-Object {'{0:x2}' -f $_ }) -join '' -split '(.{4})' -ne '' | 
ForEach-Object { 'u{0}' -f $_ }) -join ''
}
}
($temp | ConvertTo-Json) -replace '\\u', 'u' | Out-File 'C:UsersuserDownloadsdata.json'

使用.ToCharArray():更简单

$temp = foreach ($line in (Get-Content -Path 'C:UsersusersDownloadscyrillic.txt')){
$nline = $line.Split(' ', 2)
# output an object straight away so it gets collected in variable $temp
[PsCustomObject]@{
id    = $nline[0]   #stores "1" from file
value = ($nline[1].ToCharArray() | ForEach-Object {'u{0:x4}' -f [uint16]$_ }) -join ''
}
}
($temp | ConvertTo-Json) -replace '\\u', 'u' | Out-File 'C:UsersuserDownloadsdata.json'

"кириллица"将转换为u043au0438u0440u0438u043bu043bu0438u0446u0430

最新更新