在php中将UCS2/HexEncoded字符转换为UTF8

4

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

UCS2/HexEncoded characters

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

对于以下字符串:

00480065006C006C006F 将返回 'Hello'

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


你之前的问题的回答中有什么不够清晰明了的吗? - Jimmy Shelter
我需要从UCS2十六进制编码的字符串中获取UTF8,也就是说,我需要从UCS2十六进制编码返回到UTF8。 - mabukarim
2个回答

3
您可以使用hexdec()将十六进制字符转换为数字,重新组合组件字符,然后使用mb_convert_encoding()将UCS-2转换为UTF-8来重新组合十六进制表示。如我在您的另一个问题的答案中提到的那样,您仍需要注意输出编码,但是由于您明确要求使用UTF-8,因此我们将在接下来的示例中使用它。
以下是一个示例,它将UCS-2十六进制转换为本地字符串形式的UTF-8。由于PHP当前不带有hex2bin()函数,这会使事情变得非常容易,因此我们将使用在参考链接中发布的函数。我将其重命名为local_hex2bin(),以防它与将来的PHP版本或您在项目中包含的某些其他第三方代码中的定义冲突。
<?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(), comment #86123 @ php.net 此外,在调用mb_convert_encoding()之前,正如我之前在评论中提到的,您可能希望尝试检测源使用的字节序,特别是如果您的应用程序具有某些部分,其中一个或多个服务器上的CPU与其余CPU方向不同。
这是一个可以帮助您识别字节顺序标记(BOM)的链接。
Byte order mark @ Wikipedia

3
有一种更紧凑的做法:$querystring = '06450631062d0628064b06270020063906270644064500200021'; $str = pack('H*', $querystring); $ucs2string = mb_convert_encoding($str, 'UTF-8', 'UCS-2'); - Jay

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="")时出现此�。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接