6

经过相当多的搜索和测试,我发现的 PHPord()函数的 Unicode 兼容替代方案的最简单方法是:

$utf8Character = 'Ą';
list(, $ord) = unpack('N', mb_convert_encoding($utf8Character, 'UCS-4BE', 'UTF-8'));
echo $ord; # 260

我在这里找到了这个。但是,有人提到这种方法相当慢。有谁知道几乎一样简单的更有效的方法?UCS-4BE 是什么意思?

4

3 回答 3

4

您也许也可以使用 来实现此功能iconv(),但mb_convert_encoding您的方法对我来说看起来很合理。只要确保它$utf8Character是单个字符,而不是长字符串,它就会表现得相当好。

UCS-4BE 是一种 Unicode 编码,它将每个字符存储为一个 32 位(4 字节)整数。这说明了“UCS-4”;“BE”前缀表示整数以大端顺序存储。这种编码的原因是,与较小的编码(如 UTF-8 或 UTF-16)不同,它不需要代理对——每个字符都是固定大小的。

于 2012-07-03T05:03:31.427 回答
3

我刚刚写了一个polyfill缺少多字节版本的ordchr考虑到以下内容:

  • 它定义了函数mb_ord并且mb_chr仅当它们不存在时。如果它们确实存在于您的框架或某些未来版本的 PHP 中,则 polyfill 将被忽略。

  • 它使用广泛使用的mbstring扩展来进行转换。如果mbstring未加载扩展,它将使用该iconv扩展。

我还添加了 HTMLentities 编码/解码和编码/解码为 JSON 格式的功能,以及一些演示代码如何使用这些功能


代码

if (!function_exists('codepoint_encode')) {
    function codepoint_encode($str) {
        return substr(json_encode($str), 1, -1);
    }
}

if (!function_exists('codepoint_decode')) {
    function codepoint_decode($str) {
        return json_decode(sprintf('"%s"', $str));
    }
}

if (!function_exists('mb_internal_encoding')) {
    function mb_internal_encoding($encoding = NULL) {
        return ($from_encoding === NULL) ? iconv_get_encoding() : iconv_set_encoding($encoding);
    }
}

if (!function_exists('mb_convert_encoding')) {
    function mb_convert_encoding($str, $to_encoding, $from_encoding = NULL) {
        return iconv(($from_encoding === NULL) ? mb_internal_encoding() : $from_encoding, $to_encoding, $str);
    }
}

if (!function_exists('mb_chr')) {
    function mb_chr($ord, $encoding = 'UTF-8') {
        if ($encoding === 'UCS-4BE') {
            return pack("N", $ord);
        } else {
            return mb_convert_encoding(mb_chr($ord, 'UCS-4BE'), $encoding, 'UCS-4BE');
        }
    }
}

if (!function_exists('mb_ord')) {
    function mb_ord($char, $encoding = 'UTF-8') {
        if ($encoding === 'UCS-4BE') {
            list(, $ord) = (strlen($char) === 4) ? @unpack('N', $char) : @unpack('n', $char);
            return $ord;
        } else {
            return mb_ord(mb_convert_encoding($char, 'UCS-4BE', $encoding), 'UCS-4BE');
        }
    }
}

if (!function_exists('mb_htmlentities')) {
    function mb_htmlentities($string, $hex = true, $encoding = 'UTF-8') {
        return preg_replace_callback('/[\x{80}-\x{10FFFF}]/u', function ($match) use ($hex) {
            return sprintf($hex ? '&#x%X;' : '&#%d;', mb_ord($match[0]));
        }, $string);
    }
}

if (!function_exists('mb_html_entity_decode')) {
    function mb_html_entity_decode($string, $flags = null, $encoding = 'UTF-8') {
        return html_entity_decode($string, ($flags === NULL) ? ENT_COMPAT | ENT_HTML401 : $flags, $encoding);
    }
}

如何使用

echo "Get string from numeric DEC value\n";
var_dump(mb_chr(50319, 'UCS-4BE'));
var_dump(mb_chr(271));

echo "\nGet string from numeric HEX value\n";
var_dump(mb_chr(0xC48F, 'UCS-4BE'));
var_dump(mb_chr(0x010F));

echo "\nGet numeric value of character as DEC int\n";
var_dump(mb_ord('ď', 'UCS-4BE'));
var_dump(mb_ord('ď'));

echo "\nGet numeric value of character as HEX string\n";
var_dump(dechex(mb_ord('ď', 'UCS-4BE')));
var_dump(dechex(mb_ord('ď')));

echo "\nEncode / decode to DEC based HTML entities\n";
var_dump(mb_htmlentities('tchüß', false));
var_dump(mb_html_entity_decode('tchüß'));

echo "\nEncode / decode to HEX based HTML entities\n";
var_dump(mb_htmlentities('tchüß'));
var_dump(mb_html_entity_decode('tchüß'));

echo "\nUse JSON encoding / decoding\n";
var_dump(codepoint_encode("tchüß"));
var_dump(codepoint_decode('tch\u00fc\u00df'));

输出

Get string from numeric DEC value
string(4) "ď"
string(2) "ď"

Get string from numeric HEX value
string(4) "ď"
string(2) "ď"

Get numeric value of character as DEC string
int(50319)
int(271)

Get numeric value of character as HEX string
string(4) "c48f"
string(3) "10f"

Encode / decode to DEC based HTML entities
string(15) "tchüß"
string(7) "tchüß"

Encode / decode to HEX based HTML entities
string(15) "tchüß"
string(7) "tchüß"

Use JSON encoding / decoding
string(15) "tch\u00fc\u00df"
string(7) "tchüß"
于 2014-07-15T16:18:47.297 回答
0

这是我使用该公式将字符串转换为 int 的方法。您还可以分解字符串并使用 array_reduce 对其进行总结。

/**
 * @param $string
 * @param int $index
 * @return mixed
 */
function convertEncoding($string, $index = 0, $carryResult = 0)
{
    $remainder = mb_strlen(mb_substr($string, $index));
    while ($remainder) {
        $currentCharacter = $string[$index];
        list(, $ord) = unpack('N', mb_convert_encoding($currentCharacter, 'UCS-4BE', 'UTF-8'));
        return $this->convertEncoding($string, $index += 1, $ord += $carryResult);
    }
    return $carryResult;
}
于 2016-03-28T18:41:37.223 回答