PHP如何构建Unicode字符串?

8

如果要从CLI PHP脚本输出一个Unicode十进制或十六进制字符,PHP如何生成它?chr()函数似乎不能生成正确的输出。以下是我的测试脚本,使用节(Section Break)字符U+00A7(十六进制为A7,十进制为167,应表示为UTF-8中的C2 A7)作为测试:

<?php
echo "Section sign: ".chr(167)."\n"; // Using CHR function
echo "Section sign: ".chr(0xA7)."\n";
echo "Section sign: ".pack("c", 0xA7)."\n"; // Using pack function?
echo "Section sign: §\n"; // Copy and paste of the symbol into source code

我通过 SSH 连接服务器后得到的输出如下:

Section sign: ?
Section sign: ?
Section sign: ?
Section sign: §

所以,这证明我正在使用的终端字体中具有分节符号,并且SSH连接成功地发送了它,但是chr()在从代码编号构造它时没有正确构造它。

如果我只有代码编号而没有复制/粘贴选项,我有哪些选择?

5个回答

5
假设您拥有iconv,这里是一种简单的方法,无需自己实现UTF-8:
function unichr($i) {
    return iconv('UCS-4LE', 'UTF-8', pack('V', $i));
}

4

如果不使用mb_函数和iconv,PHP在排除这些函数时对Unicode没有了解。您需要自己将字符进行UTF-8编码。

关于UTF-8的结构,维基百科有一个优秀的概述。以下是一个基于该文章的快速、简单和未经测试的函数示例:

function codepointToUtf8($codepoint)
{
    if ($codepoint < 0x7F) // U+0000-U+007F - 1 byte
        return chr($codepoint);
    if ($codepoint < 0x7FF) // U+0080-U+07FF - 2 bytes
        return chr(0xC0 | ($codepoint >> 6)).chr(0x80 | ($codepoint & 0x3F);
    if ($codepoint < 0xFFFF) // U+0800-U+FFFF - 3 bytes
        return chr(0xE0 | ($codepoint >> 12)).chr(0x80 | (($codepoint >> 6) & 0x3F).chr(0x80 | ($codepoint & 0x3F);
    else // U+010000-U+10FFFF - 4 bytes
        return chr(0xF0 | ($codepoint >> 18)).chr(0x80 | ($codepoint >> 12) & 0x3F).chr(0x80 | (($codepoint >> 6) & 0x3F).chr(0x80 | ($codepoint & 0x3F);
}

一个很好的方法就是一开始就用UTF-8编写PHP文档。 - Billy ONeal
非常好的答案,Michael;感谢您提供这个函数!我使用pack函数而不是重复使用chr创建了类似的东西。Billy,针对这个特定目的,我需要从代码点转换为字符;使用已经嵌入字符的UTF-8编写PHP脚本不是一个选项。 - MidnightLightning

3

不要忘记UTF-8是一种变长编码。

§不包括在UTF-8能够用一个字节显示的前128个(ASCII)字符中。§是UTF-8中的多字节字符,由一个表示两字节序列的第一个字节c2加上后续字节组成。下面应该可以正常工作:

echo "Section sign: ".chr(0xC2).chr(0xA7)."\n"; 

3
chr

(PHP 4, PHP 5)

chr — Return a specific character

Report a bug
 Description

string chr ( int $ascii )
Returns a one-character string containing the character specified by ascii.

这个函数是 ord() 函数的补充。

重要的是 ASCII 这个词 :) 试试这个:

  function uchr ($codes) {
        if (is_scalar($codes)) $codes= func_get_args();
        $str= '';
        foreach ($codes as $code) $str.= html_entity_decode('&#'.$code.';',ENT_NOQUOTES,'UTF-8');
        return $str;
    }
    echo "Section sign: ".uchr(167)."\n"; // Using CHR function
    echo "Section sign: ".uchr(0xA7)."\n";

0

我知道我正在重新打开一个旧的、已解决的问题,但是由于我在寻求帮助时偶然发现了这个主题,所以我想分享我最终找到的解决方案。

手动重新编程 ASCII 到 Unicode 就像重新发明轮子一样,更不用说错误/性能潜力。

我找到的最佳解决方案是使用:

  1. pack 从输入数据创建值,使用适当的代码来读取正确数量的数据,通常使用 pack("H*", <input data>) 从十六进制值中读取
  2. mb_convert_encoding 将 ASCII 字符串转换为 Unicode 字符串,使用 mb_convert_encoding(<ASCII string>, "UTF-8")。如果输入字符串无法被正确识别,则此函数的第三个参数允许指定输入编码

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