Php 如何获取utf-8字符串中给定字符的代码点编号?

Php 如何获取utf-8字符串中给定字符的代码点编号?,php,unicode,Php,Unicode,我想获得给定UTF-8字符串的UCS-2代码点。例如,单词“hello”应该变成类似“0068 0065 006C 006C 006F”的东西。请注意,字符可以来自任何语言,包括复杂的脚本,如东亚语言 因此,问题归结为“将给定字符转换为其UCS-2代码点” 但是怎么做呢?请,我很忙,任何帮助都将非常感谢 提问者回答的抄写,作为答案张贴 感谢您的回复,但它需要在PHPV4或5中完成,而不是在6中 该字符串将是来自表单字段的用户输入 我想实现一个PHP版本的utf8to16或utf8decode之

我想获得给定UTF-8字符串的UCS-2代码点。例如,单词“hello”应该变成类似“0068 0065 006C 006C 006F”的东西。请注意,字符可以来自任何语言,包括复杂的脚本,如东亚语言

因此,问题归结为“将给定字符转换为其UCS-2代码点”

但是怎么做呢?请,我很忙,任何帮助都将非常感谢


提问者回答的抄写,作为答案张贴

感谢您的回复,但它需要在PHPV4或5中完成,而不是在6中

该字符串将是来自表单字段的用户输入

我想实现一个PHP版本的utf8to16或utf8decode之类的

function get_ucs2_codepoint($char)
{
    // calculation of ucs2 codepoint value and assign it to $hex_codepoint
    return $hex_codepoint;
}

您能帮助我使用PHP吗?或者可以使用上面提到的PHP版本来完成吗?

使用现有的实用程序,例如,或您使用的语言附带的任何库

如果你坚持推出自己的解决方案,请仔细阅读格式。基本上,根据代码点的值,每个代码点存储为1-4字节。范围如下:

  • U+0000-U+007F:1字节:0xxxxxxx
  • U+0080-U+07FF:2字节:110xxxxx 10xxxxxx
  • U+0800-U+FFFF:3字节:1110xxxx 10xxxxx 10xxxxxx
  • U+10000-U+10FFFF:4字节:11110xxx 10xxxxx 10xxxxx 10xxxxxx
其中每个x是一个数据位。因此,您可以通过查看第一个字节来判断每个代码点由多少字节组成:如果它以0开头,则为1字节字符。如果以110开头,则为2字节字符。如果以1110开头,则为3字节字符。如果以11110开头,则为4字节字符。如果以10开头,则为多字节字符的非初始字节。如果以11111开头,则为无效字符

一旦你计算出这个字符中有多少字节,就只不过是有点无聊了。还要注意,UCS-2不能表示U+FFFF以上的字符

由于您没有指定语言,下面是一些示例C代码(省略了错误检查):

wchar_t utf8_char_to_ucs2(const unsigned char*utf8)
{
如果(!(utf8[0]&0x80))//0xxxxxxx
返回(wchar_t)utf8[0];
如果((utf8[0]&0xE0)==0xC0)//110xxxxx

return(wchar_t)((utf8[0]&0x1F)我很开心,因为我刚刚在期末考试中给学生们出了这个问题。下面是UTF-8的草图:

hex         binary                   UTF-8 binary
0000-007F   00000000 0abcdefg   =>   0abcdefg
0080-07FF   00000abc defghijk   =>   110abcde 10fghijk
0800-FFFF   abcdefgh ijklmnop   =>   1110abcd 10efghij 10klmnop
下面是一些C99代码:

static void check(char c) {
  if ((c & 0xc0) != 0xc0) RAISE(Bad_UTF8);
}

uint16_t Utf8_decode(char **p) { // return code point and advance *p
  char *s = *p;
  if ((s[0] & 0x80) == 0) {
    (*p)++;
    return s[0];
  } else if ((s[0] & 0x40) == 0) {
    RAISE (Bad_UTF8);
    return ~0; // prevent compiler warning
  } else if ((s[0] & 0x20) == 0) {
    if ((s[0] & 0xf0) != 0xe0) RAISE (Bad_UTF8);
    check(s[1]); check(s[2]);
    (*p) += 3;
    return ((s[0] & 0x0f) << 12)
         + ((s[1] & 0x3f) <<  6)
         + ((s[2] & 0x3f));
  } else {
    check(s[1]);
    (*p) += 2;
    return ((s[0] & 0x1f) << 6)
         + ((s[1] & 0x3f));
  }
}    
静态无效检查(字符c){
如果((c&0xc0)!=0xc0)上升(坏的UTF8);
}
uint16_t Utf8_解码(字符**p){//返回代码点和前进*p
char*s=*p;
如果((s[0]&0x80)==0){
(*p)++;
返回s[0];
}else如果((s[0]&0x40)==0){
升起(坏的_UTF8);
返回~0;//防止编译器警告
}else if((s[0]&0x20)==0){
如果((s[0]&0xf0)!=0xe0)上升(错误的UTF8);
支票[1];支票[2];
(*p)+=3;
return((s[0]&0x0f)向写入了一个函数。我发现它正在查看

函数utf8到unicode($str){ $unicode=array(); $values=array(); $lookingFor=1; 对于($i=0;$i=ord('0')&&$thisValuePHP代码(假定有效的utf-8,不检查无效的utf-8):

功能ord_utf8($c){ $b0=作战需求文件($c[0]); 如果($b0<0x10){ 返回$b0; } $b1=作战需求文件($c[1]); 如果($b0<0xE0){ 返回($b0&0x1F)在
php>=7.2
中使用
mb_ord()

或此功能:

function ord_utf8($c) {
    $len = strlen($c);
    $code = ord($c);
    if($len > 1) {
        $code &= 0x7F >> $len;
        for($i = 1; $i < $len; $i++) {
            $code <<= 6;
            $code += ord($c[$i]) & 0x3F;
        }
    }
    return $code;
}

哎哟,很抱歉在C代码上浪费您的时间。但我希望这个小图表对您有所帮助。check()函数是否已损坏?它是否应该测试:if((C&0xC0)!=0x80)?还有,RAISE宏是什么?感谢check()中的错误修复函数。为我在期末考试前一天晚上写代码服务。加薪是从。我写了那个函数。原始函数在这里,还有一些你可能会发现有用的函数:@Reynen,小世界,嗯?我编辑了我的帖子,给你信用和一些广告。请,哦,请叫它
utf8\u to\u utf16
。两者都是“Unicode”表示为Unicode代码点。@ScottReynen 404 link,您还有原始的吗?很好,只是当字符已经是ASCII时它失败了。0x10应该是0x80,以捕获完整的ASCII范围。
function utf8_to_unicode( $str ) {

    $unicode = array();        
    $values = array();
    $lookingFor = 1;

    for ($i = 0; $i < strlen( $str ); $i++ ) {
        $thisValue = ord( $str[ $i ] );
    if ( $thisValue < ord('A') ) {
        // exclude 0-9
        if ($thisValue >= ord('0') && $thisValue <= ord('9')) {
             // number
             $unicode[] = chr($thisValue);
        }
        else {
             $unicode[] = '%'.dechex($thisValue);
        }
    } else {
          if ( $thisValue < 128) 
        $unicode[] = $str[ $i ];
          else {
                if ( count( $values ) == 0 ) $lookingFor = ( $thisValue < 224 ) ? 2 : 3;                
                $values[] = $thisValue;                
                if ( count( $values ) == $lookingFor ) {
                    $number = ( $lookingFor == 3 ) ?
                        ( ( $values[0] % 16 ) * 4096 ) + ( ( $values[1] % 64 ) * 64 ) + ( $values[2] % 64 ):
                        ( ( $values[0] % 32 ) * 64 ) + ( $values[1] % 64 );
            $number = dechex($number);
            $unicode[] = (strlen($number)==3)?"%u0".$number:"%u".$number;
                    $values = array();
                    $lookingFor = 1;
          } // if
        } // if
    }
    } // for
    return implode("",$unicode);

} // utf8_to_unicode
function ord_utf8($c) {
    $b0 = ord($c[0]);
    if ( $b0 < 0x10 ) {
        return $b0;
        }
    $b1 = ord($c[1]);
    if ( $b0 < 0xE0 ) {
        return (($b0 & 0x1F) << 6) + ($b1 & 0x3F);
        }
    return (($b0 & 0x0F) << 12) + (($b1 & 0x3F) << 6) + (ord($c[2]) & 0x3F);
    }
function ord_utf8($c) {
    $len = strlen($c);
    $code = ord($c);
    if($len > 1) {
        $code &= 0x7F >> $len;
        for($i = 1; $i < $len; $i++) {
            $code <<= 6;
            $code += ord($c[$i]) & 0x3F;
        }
    }
    return $code;
}
$string = 'abcde';
$string = preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY);