tl;dr有没有办法将存储在hashtable中的cyrillic转换为UTF-16?将кириллица
类似于u043au0438u0440u0438u043bu043bu0438u0446u0430
我需要导入文件,将其解析为id
和value
,然后将其转换为.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