4

我之前问了一个问题,从 UTF-8 获取 UCS-2/HexEncoded 字符串,我在以下链接中得到了一些人的帮助。

UCS2/HexEncoded 字符

但现在我需要从 PHP 中的 UCS-2/HexEncoded 字符串中获取正确的 UTF-8。

对于以下字符串:

00480065006C006C006F 将返回“你好”

06450631062d0628064b06270020063906270644064500200021 将以阿拉伯语返回 (!مرحبا عالم)

4

2 回答 2

3

您可以通过使用hexdec()转换十六进制字符,重新打包组件字符,然后使用mb_convert_encoding()从 UCS-2 转换为 UTF-8 来重构十六进制表示。正如我在对您的其他问题的回答中提到的那样,您仍然需要小心输出编码,尽管您在这里特别要求使用 UTF-8,因此我们将在即将到来的示例中使用它。

这是一个将 Hex 中的 UCS-2 转换为原生字符串形式的 UTF-8 的示例。由于 PHP 目前没有附带hex2bin()函数,这会使事情变得非常简单,我们将使用最后发布在参考链接中的那个。我已将其重命名为local_hex2bin()以防它与 PHP 的未来版本或您在项目中包含的其他一些 3rd 方代码中的定义发生冲突。

<?php
function local_hex2bin($h)
{
if (!is_string($h)) return null;
$r='';
for ($a=0; $a<strlen($h); $a+=2) { $r.=chr(hexdec($h{$a}.$h{($a+1)})); }
return $r;
};

header('Content-Type: text/html; charset=UTF-8');
mb_http_output('UTF-8');
echo '<html><head>';
echo '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
echo '</head><body>';
echo 'output encoding: '.mb_http_output().'<br />';
$querystring = $_SERVER['QUERY_STRING'];
// NOTE: we could substitute one of the following:
// $querystring = '06450631062d0628064b06270020063906270644064500200021';
// $querystring = '00480065006C006C006F';
$ucs2string = local_hex2bin($querystring);
// NOTE: The source encoding could also be UTF-16 here.
// TODO: Should check byte-order-mark, if available, in case
//       16-bit-aligned bytes are reversed.
$utf8string = mb_convert_encoding($ucs2string, 'UTF-8', 'UCS-2');
echo 'query string: '.$querystring.'<br />';
echo 'converted string: '.$utf8string.'<br />';
echo '</body>';
?>

在本地,我将此示例页面称为 UCS2HexToUTF8.php,然后使用查询字符串设置输出。

UCS2HexToUTF8.php?06450631062d0628064b06270020063906270644064500200021
--
encoding: UTF-8
query string: 06450631062d0628064b06270020063906270644064500200021
converted string: مرحبًا عالم !

UCS2HexToUTF8.php?00480065006C006C006F
--
output encoding: UTF-8
query string: 00480065006C006C006F
converted string: Hello

这是hex2bin()函数的原始来源的链接。
PHP:bin2hex(),评论 #86123 @ php.net

此外,正如我在调用mb_convert_encoding()之前的评论中所指出的那样,您可能想要尝试检测源正在使用哪种字节序,特别是如果您的应用程序具有一台服务器上的一个或多个 CPU 不同于其余的按方向。

这是一个可以帮助您识别字节顺序标记 (BOM) 的链接。
字节顺序标记@维基百科

于 2010-01-05T17:24:09.077 回答
1

UCS-2 到 UTF-8 的更准确转换

function ucs2_to_utf8($h)
{
    if (!is_string($h)) return null;
    $r='';
    for ($a=0; $a<strlen($h); $a+=4) { $r.=chr(hexdec($h{$a}.$h{($a+1)}.$h{($a+2)}.$h{($a+3)})); }
    return $r;
}

所选答案的问题是它除以 2 而不是 4,这会导致将 00 转换为 null 并且会导致当它用于 html 属性值(如 title="" 或 alt=""

于 2018-10-02T13:48:56.963 回答