这个问题看起来很尴尬,但我一直找不到答案。
与下面的C#代码行等效的PHP是什么?
string str = "\u1000";
此示例创建一个带有单个Unicode字符的字符串,该字符串的“ Unicode数值”为十六进制的1000(十进制的4096)。
也就是说,在PHP中,如何创建一个具有“ Unicode数值”已知的Unicode字符的字符串?
这个问题看起来很尴尬,但我一直找不到答案。
与下面的C#代码行等效的PHP是什么?
string str = "\u1000";
此示例创建一个带有单个Unicode字符的字符串,该字符串的“ Unicode数值”为十六进制的1000(十进制的4096)。
也就是说,在PHP中,如何创建一个具有“ Unicode数值”已知的Unicode字符的字符串?
Answers:
因为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');
\uxxxx
Unicode语法,因此您可以使用它json_decode
来人工创建的JSON字符串表示形式。我更改了措辞,但已将其澄清。
echo json_decode('"\u201B"');
。unicode符号周围的双引号是必需的。
PHP 7.0.0引入了“ Unicode代码点转义”语法。
现在,可以通过使用双引号或Heredoc字符串轻松编写Unicode字符,而无需调用任何函数。
$unicodeChar = "\u{1000}";
我想知道为什么还没有人提到这一点,但是您可以在双引号字符串中使用转义序列来做一个几乎等效的版本:
\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 big endian一致,因此我们可以这样直接打印出来:
<?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
功能,但是您可以预期它会很慢。
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);
}
或使用匿名函数表达式代替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");
尝试便携式UTF-8:
$str = utf8_chr( 0x1000 );
$str = utf8_chr( '\u1000' );
$str = utf8_chr( 4096 );
所有工作方式都完全相同。您可以使用获取字符的代码点utf8_ord()
。阅读有关便携式UTF-8的更多信息。
正如其他人提到的,PHP 7 \u
直接引入了对Unicode语法的支持。
正如其他人提到的那样,从PHP中任何明智的Unicode字符描述中获取字符串值的唯一方法是通过将其转换为其他内容(例如JSON解析,HTML解析或其他形式)。但这是以运行时性能成本为代价的。
但是,还有另一种选择。您可以使用\x
二进制转义直接在PHP中对字符进行编码。该\x
转义语法也支持PHP 5。
如果您不想通过字符的自然形式直接在字符串中输入字符,这将特别有用。例如,如果它是一个不可见的控制字符,或其他难以检测到的空格。
首先,举一个例子:
// Unicode Character 'HAIR SPACE' (U+200A)
$htmlEntityChar = " ";
$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(' ') . "\n";
// \xe2\x80\x8a
// Example for JSON: Unicode Character 'HAIR SPACE' (U+200A)
echo str_convert_json_to_utf8binary('"\u200a"') . "\n";
// \xe2\x80\x8a