【发布时间】:2021-01-30 01:43:23
【问题描述】:
我从图书馆收到国家/地区名称:"\u00c3\u0096sterreich"。
如何将其转换为Österreich?
使用 PHP 7.3
【问题讨论】:
标签: php
我从图书馆收到国家/地区名称:"\u00c3\u0096sterreich"。
如何将其转换为Österreich?
使用 PHP 7.3
【问题讨论】:
标签: php
这个比看起来要复杂得多,但下面的代码似乎可以工作。
首先,我们通过 Unicode 转义序列的标准正则表达式对其进行管道传输,然后将其打包为二进制字符串,转换编码并最终解码。我不能保证这是最好的方法,但据我所知,它似乎工作正常。
$str = '\u00c3\u0096sterreich';
$str = preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/', function ($match) {
return utf8_decode(mb_convert_encoding(pack('H*', $match[1]), 'UTF-8', 'UCS-2BE'));
}, $str);
【讨论】:
UTF-8 字符“Ö”的 Unicode 是 U+00D6。 该字符由 2 个十六进制字节组成:c3 和 96。 这 2 个字节的表示 \u00c3 \u0096 有点奇怪。假设多字节字符逐字节表示,也可以使用下面的代码。
$str = '\u00c3\u0096sterreich';
$str = preg_replace_callback(
'~\\\\u00([0-9a-f]{2})~i',
function($m){
return hex2bin($m[1]);
},
$str
);
//Test
$expect = "Österreich";
var_dump($str === $expect); //bool(true)
【讨论】:
如果其他人在这里遇到类似的问题,我想我会尝试对正在发生的事情有所了解。因为如前所述,这看起来要复杂得多。
像\u00c3 这样的字符串是指十六进制的Unicode 代码点。 Unicode 表中的 Ö 是字符 214,或 \u00d6。
这里的 214 与 Ö 以任何特定编码(UTF-8、UTF-16 等)的实际存储方式没有直接关系,它只是整个 Unicode 表中引用该字符的一个抽象数字。例如,UTF-8 会将其存储在两个字节 11000010 10010110(十进制为 194 150)中。 this answer 中有一个很好的解释说明这是如何工作的,如果您对更详细的细节感兴趣的话。
您的字符串中似乎发生的事情是,这两个字节随后被编码为 back 十六进制,并作为两个单独的 Unicode 代码点返回。 u00c3 是 Ã,\u0096 是控制字符。这就是为什么任何标准解码方法(json_decode 等)都不起作用的原因 - 最终你所拥有的不是字符串 Österreich 的有效表示。
其他答案应该都可以很好地工作,但是这段代码 sn-p 可能更好地说明您的库使用的格式问题。它专门匹配两个连续的低 Unicode 代码点,将它们的十进制表示重新组合成一个无符号的两字节整数,然后返回结果。
$str = '\u00c3\u0096sterreich';
echo preg_replace_callback('/\\\\u00([0-9a-fA-F]{2})\\\\u00([0-9a-fA-F]{2})/', function ($match) {
$i = (hexdec($match[1]) << 8) + hexdec($match[2]);
return pack('N', $i);
}, $str);
奥斯特雷赫
【讨论】: