如何用php显示中文字符的utf-8和unicode值?

时间:2015-04-11 15:14:56

标签: php unicode encoding utf-8

在python中,我可以获得 utf-8 内容和中文字符的Unicode。

python version 3.4
>>> print("你".encode("utf-8"))
b'\xe4\xbd\xa0'
>>> print("你".encode("unicode-escape"))
b'\\u4f60'

如何显示的utf-8和unicode值(意思是英文) 用PHP在网上?如何使用'\xe4\xbd\xa0'在firefox中使用python获得相同的输出\\u4f60php

1 个答案:

答案 0 :(得分:1)

第一个例子是显示utf-8编码的字节;因此,假设字符串是utf-8编码的,您只需打印每个字符的十六进制ACSII值。

$str = "你";

foreach (str_split($str) as $byte) {
    echo '\\x'.str_pad(dechex(ord($byte)), 2, '0', STR_PAD_LEFT);
}

// prints: \xe4\xbd\xa0

第二行是为角色打印Unicode code point。由于php字符串只是单字节,我们必须首先解码字节以访问代码点,然后格式化十六进制数字。

根据WHATWG Encoding Standard,我们可以utf-8 decoder对代码点进行解码,包括supplementary code points

// Decodes a utf-8 encoded string and returns an array
// of code points or null if there was an error
// https://encoding.spec.whatwg.org/#utf-8-decoder
function decode_utf8($str)
{
    $code_point = 0;
    $bytes_needed = 0;
    $bytes_seen = 0;

    $lower_boundary = 0x80;
    $upper_boundary = 0xbf;

    $code_points = array();

    for ($i = 0, $len = strlen($str); $i < $len; $i++) {
        $byte = ord($str[$i]);

        if ($bytes_needed == 0) {
            if ($byte >= 0x00 and $byte <= 0x7f) {
                $code_points[] = $byte;
            } elseif ($byte >= 0xc2 and $byte <= 0xdf) {
                $bytes_needed = 1;
                $code_point = $byte - 0xc0;
            } elseif ($byte >= 0xe0 and $byte <= 0xef) {
                if ($byte == 0xe0) {
                    $lower_boundary = 0xa0;
                }
                if ($byte == 0xed) {
                    $upper_boundary = 0x9f;
                }

                $bytes_needed = 2;
                $code_point = $byte - 0xe0;
            }  elseif ($byte >= 0xf0 and $byte <= 0xf4) {
                if ($byte == 0xf0) {
                    $lower_boundary = 0x90;
                }
                if ($byte == 0xf4) {
                    $upper_boundary = 0x8f;
                }

                $bytes_needed = 3;
                $code_point = $byte - 0xf0;
            }  else {
                return;
            }

            $code_point = $code_point << (6 * $bytes_needed);
            continue;
        }

        if ($byte < $lower_boundary or $byte > $upper_boundary) {
            return;
        }

        $lower_boundary = 0x80;
        $upper_boundary = 0xbf;

        $bytes_seen++;
        $code_point += ($byte - 0x80) << (6 * ($bytes_needed - $bytes_seen));

        if ($bytes_seen != $bytes_needed) {
            continue;
        }

        $code_points[] = $code_point;

        $code_point = 0;
        $bytes_needed = 0;
        $bytes_seen = 0;
    }

    if ($bytes_needed != 0) {
        return;
    }

    return $code_points;
}

解码代码点后,我们将其转换为带有dechex的十六进制。然后,使用str_pad,我们用零填充它们。如果代码点在基本的多语言平面中,我们将它填充为四个字符长,否则我们将它设为六个字符长。最后,我们在开头添加\u

$str = '你';

foreach (decode_utf8($str) as $code_point) {
    echo '\\u'.str_pad(dechex($code_point), $code_point>0xffff?6:4, '0', STR_PAD_LEFT);
}
// prints: \u4f60

它也适用于基本多语言平面之外的角色,例如CJK Ideograph Extensions

$str = ''; // U+020000

foreach (decode_utf8($str) as $code_point) {
    echo '\\u'.str_pad(dechex($code_point), $code_point>0xffff?6:4, '0', STR_PAD_LEFT);
}
// prints: \u020000