2010-09-13 129 views
7

给定一个Unicode十进制或十六进制数字,希望从CLI PHP脚本输出一个字符,PHP如何生成它? chr()函数似乎不会生成正确的输出。这里是我的测试脚本,使用分节符字符U + 00A7作为测试(A7十六进制,167十进制,应在UTF-8被表示为C2 A7):PHP构造一个Unicode字符串?

<?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会话服务器)是:

所以,这证明了我使用的终端字体中有节间隔字符和SSH连接沿着发送成功,但chr() ISN”从代码编号构造它时,应该正确地构造它。

如果我得到的只是代码编号而不是复制/粘贴选项,我有什么选择?

回答

4

在排除mb_函数和iconv时,PHP不知道Unicode。你必须自己编码UTF-8。

为此,维基百科有关如何构造UTF-8的excellent overview。这里有一个基于该文章的快速,肮脏和未经测试的功能:

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); 
} 
+0

一个很好的方法就是首先编写UTF-8中的PHP文档。迈克尔;优秀的答案, – 2010-09-13 21:34:38

+0

并感谢功能!我为自己创建了一个类似于使用pack函数而非chr的类似的东西。比利,为了这个特定的目的,我需要从一个代码点到一个角色;使用已经嵌入的字符编写UTF-8的PHP脚本不是一种选择。 – MidnightLightning 2010-09-13 22:10:32

3

不要忘了UTF-8是一种可变长度编码。

§不包含在UTF-8能够在一个字节中显示的前128个(ASCII)字符中。 §是UTF-8中的多字节字符,前面加上c2字节,表示first byte of a two-byte sequence.。这应该工作:

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"; 
5

假设你有iconv,这里不涉及执行一个简单的方法UTF-8自己:

function unichr($i) { 
    return iconv('UCS-4LE', 'UTF-8', pack('V', $i)); 
} 
0

我知道我正在重新开放一个已解决的旧问题,但是由于我偶然发现了那个寻求帮助的主题,我想我会分享我最终解决的问题。 提出问题的初始人可能有兴趣重构他/她的代码以获得最佳效果。

手动重新编程ascii-to-unicode就像重新发明轮子,而不是谈论错误/性能潜力。

我发现,最好的解决方案是使用:

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