PHP字符串中的Unicode字符

Posted

技术标签:

【中文标题】PHP字符串中的Unicode字符【英文标题】:Unicode character in PHP string 【发布时间】:2011-08-28 20:10:17 【问题描述】:

这个问题看起来简单得令人尴尬,但我一直找不到答案。

php 相当于以下 C# 行代码是什么?

string str = "\u1000";

此示例创建一个包含单个 Unicode 字符的字符串,其“Unicode 数值”为十六进制的1000(十进制的4096)。

也就是说,在 PHP 中,我怎样才能创建一个包含单个 Unicode 字符且其“Unicode 数值”已知的字符串?

【问题讨论】:

阅读:php.net/manual/en/regexp.reference.unicode.php @diEcho:这仅用于匹配 Unicode 字符,但 OP 想要创建这些字符。 这可能会有所帮助:randomchaos.com/documents/?source=php_and_unicode How to decode Unicode escape sequences like "\u00ed" to proper UTF-8 encoded characters?的可能重复 这个问题有 10 年历史了。接受的答案已经过时了。 【参考方案1】:

因为 JSON 直接支持 \uxxxx 语法,所以我首先想到的是:

$unicodeChar = '\u1000';
echo json_decode('"'.$unicodeChar.'"');

另一种选择是使用mb_convert_encoding()

echo mb_convert_encoding('က', 'UTF-8', 'html-ENTITIES');

或利用 UTF-16BE(大端)和 Unicode 代码点之间的直接映射:

echo mb_convert_encoding("\x10\x00", 'UTF-8', 'UTF-16BE');

【讨论】:

@Gumbo:我知道,但在这里没有任何区别。 javascript 和 JSON 支持 \uxxxx Unicode 语法,因此您可以使用 json_decode 处理人工创建的 JSON 字符串表示。我更改了措辞以澄清这一点。 好的,所以对我的问题的一个答案的严格表述是: $str=json_decode('"\u1000"');谢谢。 我试过 echo json_decode('\u201B'); 引用 single reverted quote 但是它不起作用,这意味着没有输出(即使通过管道传输到 hd 你需要echo json_decode('"\u201B"');。 unicode 符号周围的双引号是强制性的。 是否可以使用一些 PHP 常量来代替纯字符串 'HTML-ENTITIES''UTF-8'【参考方案2】:

PHP 不知道这些 Unicode 转义序列。但由于未知转义序列不受影响,您可以编写自己的函数来转换此类 Unicode 转义序列:

function unicodeString($str, $encoding=null) 
    if (is_null($encoding)) $encoding = ini_get('mbstring.internal_encoding');
    return preg_replace_callback('/\\\\u([0-9a-fA-F]4)/u', create_function('$match', 'return mb_convert_encoding(pack("H*", $match[1]), '.var_export($encoding, true).', "UTF-16BE");'), $str);

或者用anonymous function expression 代替create_function

function unicodeString($str, $encoding=null) 
    if (is_null($encoding)) $encoding = ini_get('mbstring.internal_encoding');
    return preg_replace_callback('/\\\\u([0-9a-fA-F]4)/u', function($match) use ($encoding) 
        return mb_convert_encoding(pack('H*', $match[1]), $encoding, 'UTF-16BE');
    , $str);

它的用法:

$str = unicodeString("\u1000");

【讨论】:

【参考方案3】:
html_entity_decode('エ', 0, 'UTF-8');

这也有效。但是 json_decode() 解决方案要快得多(大约 50 倍)。

【讨论】:

简单、优雅、直接且完全安全的方法。 +10【参考方案4】:

试试Portable UTF-8:

$str = utf8_chr( 0x1000 );
$str = utf8_chr( '\u1000' );
$str = utf8_chr( 4096 );

所有的工作方式完全相同。您可以使用utf8_ord() 获取字符的代码点。 Read more about Portable UTF-8.

【讨论】:

【参考方案5】:

我想知道为什么还没有人提到这一点,但你可以使用double quoted strings 中的转义序列做一个几乎等效的版本:

\x[0-9A-Fa-f]1,2

匹配正则表达式的字符序列是 十六进制字符。

ASCII 示例:

<?php
    echo("\x48\x65\x6C\x6C\x6F\x20\x57\x6F\x72\x6C\x64\x21");
?>

世界你好!

因此,对于您的情况,您只需$str = "\x30\xA2";。但这些是字节,而不是字符。 Unicode 代码点的字节表示与 UTF-16 大端一致,因此我们可以直接打印出来:

<?php
    header('content-type:text/html;charset=utf-16be');
    echo("\x30\xA2");
?>

如果您使用不同的编码,则需要相应地更改字节(主要通过库完成,但也可以手动完成)。

UTF-16 小端示例:

<?php
    header('content-type:text/html;charset=utf-16le');
    echo("\xA2\x30");
?>

UTF-8 示例:

<?php
    header('content-type:text/html;charset=utf-8');
    echo("\xE3\x82\xA2");
?>

还有pack 函数,但你可以预料它会很慢。

【讨论】:

非常适合在复制/粘贴项目符号字符 (\xE2\x80\xA2) 时可能导致源文档中出现 UTF-8 编码错误。谢谢。【参考方案6】:

PHP 7.0.0 引入了"Unicode codepoint escape" syntax。

现在可以使用double-quoted 或heredoc 字符串轻松编写Unicode 字符,而无需调用任何函数。

$unicodeChar = "\u1000";

【讨论】:

这个可以这样使用:wordwrap($longLongText, 20, "\u200B", true);(zero-width space是) 我相信 OP 想要这个答案,而不是接受的答案。无论如何,当我搜索“PHP 中的 Unicode”时,是因为我想要这个答案,而不是接受的答案。当第一次提出这个问题时,也许“\uabcd”并不存在。如果是这样,现在应该移动接受的答案。 OP 显然对所提供的答案感到沮丧,因此在对已接受答案的评论中提出了他自己的答案,这可能就是为什么这是已接受的答案而事实并非如此。正如亚当所暗示的那样,这个答案是他正在寻找的,并且考虑到 PHP 版本 7.1.33 在他询问时已经发布,我怀疑如果它没有迟到 2 年发布,这将是公认的答案。【参考方案7】:

正如其他人所提到的,PHP 7 直接引入了对\u Unicode 语法的支持。

正如其他人所提到的,从 PHP 中任何合理的 Unicode 字符描述中获取字符串值的唯一方法是将其从其他内容(例如 JSON 解析、HTML 解析或其他形式)转换。但这是以运行时性能为代价的。

但是,还有另一种选择。您可以使用 \x 二进制转义直接在 PHP 中对字符进行编码。 \x 转义语法也在 PHP 5 中得到支持

如果您不想通过自然形式直接在字符串中输入字符,这将特别有用。例如,如果它是不可见的控制字符,或其他难以检测的空格。

首先,一个证明例子:

// Unicode Character 'HAIR SPACE' (U+200A)
$htmlEntityChar = "&#8202;";
$realChar = html_entity_decode($htmlEntityChar);
$phpChar = "\xE2\x80\x8A";
echo 'Proof: ';
var_dump($realChar === $phpChar); // bool(true)

请注意,正如 Pacerier 在另一个答案中所提到的,此二进制代码对于特定的字符编码是唯一的。在上面的例子中,\xE2\x80\x8A 是 UTF-8 中 U+200A 的二进制编码。

下一个问题是,如何从U+200A\xE2\x80\x8A

下面是一个 PHP 脚本,用于为任何字符生成转义序列,基于 JSON 字符串、HTML 实体或任何其他方法(一旦您将其作为本机字符串)。

function str_encode_utf8binary($str) 
    /** @author Krinkle 2018 */
    $output = '';
    foreach (str_split($str) as $octet) 
        $ordInt = ord($octet);
        // Convert from int (base 10) to hex (base 16), for PHP \x syntax
        $ordHex = base_convert($ordInt, 10, 16);
        $output .= '\x' . $ordHex;
    
    return $output;


function str_convert_html_to_utf8binary($str) 
    return str_encode_utf8binary(html_entity_decode($str));

function str_convert_json_to_utf8binary($str) 
    return str_encode_utf8binary(json_decode($str));


// Example for raw string: Unicode Character 'INFINITY' (U+221E)
echo str_encode_utf8binary('∞') . "\n";
// \xe2\x88\x9e

// Example for HTML: Unicode Character 'HAIR SPACE' (U+200A)
echo str_convert_html_to_utf8binary('&#8202;') . "\n";
// \xe2\x80\x8a

// Example for JSON: Unicode Character 'HAIR SPACE' (U+200A)
echo str_convert_json_to_utf8binary('"\u200a"') . "\n";
// \xe2\x80\x8a

【讨论】:

【参考方案8】:
function unicode_to_textstring($str)

    $rawstr = pack('H*', $str);

    $newstr =  iconv('UTF-16BE', 'UTF-8', $rawstr);
    return $newstr;

$msg = '67714eac99c500200054006f006b0079006f002000530074006100740069006f006e003a0020';

echo unicode_to_textstring($str);

【讨论】:

以上是关于PHP字符串中的Unicode字符的主要内容,如果未能解决你的问题,请参考以下文章

PHP输出json数据时,中文不进行unicode编码

PHP:恢复转义的Unicode字符[重复]

PHP正则表达式中的UTF-8 [重复]

php - 如何将 unicode 转换为 utf-8 字符串

使用PHP和MySQL存储和显示unicode字符串(हिन्दी)

PHP Pear Mail 无法发送带有 Unicode 字符的名称