Вопрос по character-encoding, javascript, php, utf-8 – UTF-8 безопасный эквивалент ord или charCodeAt () в PHP

13

Мне нужно иметь возможность использовать ord (), чтобы получить то же значение, что и функция charCodeAt () javascript. Проблема состоит в том, что ord () не поддерживает UTF8.

Как я могу получить & # x104; перевести на 260 в PHP? Я пробовал некоторые уникальные функции, но они все сообщают 256 вместо 260.

Большое спасибо за любую помощь!

С уважением

PHP или JavaScript? hakre
@alex It'sĄ неA bardiir
Извините, должно было быть более ясным. PHP Rila
@bardiir Да, я понял это сразу после публикации. alex

Ваш Ответ

4   ответа
8

ord() работает байт за байтом (как большинство стандартных строковых функций PHP - если не все). Вам нужно будет преобразовать его самостоятельно, например, с помощью многобайтового расширения строки:

list(, $ord) = unpack('N', mb_convert_encoding($utf8Character, 'UCS-4BE', 'UTF-8'));
echo $ord; # 260
Это кажется близким, хотя Rila
Ах я вижу. Но когда я выполняю код над ним, он ничего не выводит (он пустой). Любые идеи, как превратить это в хоумран? Rila
Хм, функция списка работает неправильно? Rila
print_r дает мне массив ([1] = & gt; 260), что довольно странно, что он не индексируется нулем, но пока он работает, я счастлив :) Спасибо! Rila
list это не функция, а особая форма;list($ord) = $someArray в основном то же самое, что$ord = $someArray[0]. list удобно, когда вы хотите назначить элементы массива нескольким переменным или обойти тот факт, что вы не можете добавить нижний индекс к выражению массива, которое не является реальной переменной массива в PHP & lt; 5.4.
4


function uniord($c) {
        $h = ord($c{0});
        if ($h <= 0x7F) {
            return $h;
        } else if ($h < 0xC2) {
            return false;
        } else if ($h <= 0xDF) {
            return ($h & 0x1F) << 6 | (ord($c{1}) & 0x3F);
        } else if ($h <= 0xEF) {
            return ($h & 0x0F) << 12 | (ord($c{1}) & 0x3F) << 6
                                     | (ord($c{2}) & 0x3F);
        } else if ($h <= 0xF4) {
            return ($h & 0x0F) << 18 | (ord($c{1}) & 0x3F) << 12
                                     | (ord($c{2}) & 0x3F) << 6
                                     | (ord($c{3}) & 0x3F);
        } else {
            return false;
        }
    }
    echo uniord('Ą');
ну, на самом деле я также получил его из какого-то источника, который в настоящее время я не помню, так как у меня был этот код долгое время, извините за это, но я надеюсь, что функция поможет вам решить проблему
Спасибо Судхир, это работает! Каков источник этой функции? Rila
Внедрение UTF-8 вручную - это весело и все; Я делал это несколько раз. Но я думаю, что разумнее использовать библиотеки, поддерживаемые кем-то другим. Тем более что вы можете обрабатывать и другие кодировки.
11

function utf8_char_code_at($str, $index)
{
    $char = mb_substr($str, $index, 1, 'UTF-8');

    if (mb_check_encoding($char, 'UTF-8')) {
        $ret = mb_convert_encoding($char, 'UTF-32BE', 'UTF-8');
        return hexdec(bin2hex($ret));
    } else {
        return null;
    }
}

используя htmlspecialchars и htmlspecialchars_decode для получения одного символа:

function utf8_char_code_at($str, $index)
{
    $char = '';
    $str_index = 0;

    $str = utf8_scrub($str);
    $len = strlen($str);

    for ($i = 0; $i < $len; $i += 1) {

        $char .= $str[$i];

        if (utf8_check_encoding($char)) {

            if ($str_index === $index) {
                return utf8_ord($char);
            }

            $char = '';
            $str_index += 1;
        }
    }

    return null;
}

function utf8_scrub($str)
{
    return htmlspecialchars_decode(htmlspecialchars($str, ENT_SUBSTITUTE, 'UTF-8'));
}

function utf8_check_encoding($str)
{
    return $str === utf8_scrub($str);
}

function utf8_ord($char)
{
    $lead = ord($char[0]);

    if ($lead < 0x80) {
        return $lead;
    } else if ($lead < 0xE0) {
        return (($lead & 0x1F) << 6) 
      | (ord($char[1]) & 0x3F);
    } else if ($lead < 0xF0) {
        return (($lead &  0xF) << 12)
     | ((ord($char[1]) & 0x3F) <<  6)
     |  (ord($char[2]) & 0x3F);
    } else {
        return (($lead &  0x7) << 18)
     | ((ord($char[1]) & 0x3F) << 12)
     | ((ord($char[2]) & 0x3F) <<  6)
     |  (ord($char[3]) & 0x3F);
    }
}

Версия расширения PHP:

#include "ext/standard/html.h"
#include "ext/standard/php_smart_str.h"

const zend_function_entry utf8_string_functions[] = {
    PHP_FE(utf8_char_code_at, NULL)
    PHP_FE_END
};

PHP_FUNCTION(utf8_char_code_at)
{
    char *str;
    int len;
    long index;

    unsigned int code_point;
    long i;
    int status;
    size_t pos = 0, old_pos = 0;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &str, &len, &index) == FAILURE) {
        return;
    }

    for (i = 0; pos < len; ++i) {
        old_pos = pos;
        code_point = php_next_utf8_char((const unsigned char *) str, (size_t) len, &pos, &status);

        if (i == index) {
            if (status == SUCCESS) {
                RETURN_LONG(code_point);
            } else {
                RETURN_NULL();
            }

        }

    }

    RETURN_NULL();
}
Благодарю. Я добавил еще один пример, используя htmlspecialchars и htmlspecialchars_decode. Я написал для чтения исходного кода PHP и практики языка Си. Я подумываю предложить новую строковую функцию для ядра mbstring или PHP. Эта функция соответствует Ruby 'each_char'. Эта функция может использоваться для определения резервных функций, таких как mb_strlen и mb_substr. Я реализовал эту функцию как расширение PHP:blog.sarabande.jp/post/57645700697 (извините за японскую статью).
Вот это да. Это так же, какinsanely сложный для чего-то, что должно быть тривиальным встроенным в собственно язык! Я дам тебе +1 за усилие, но вау, просто вау!
-1

Есть одинord_utf8 функция здесь: https://stackoverflow.com/a/42600959/7558876

Эта функция выглядит так(accept string and return integer)

<?php

function ord_utf8($s){
return (int) ($s=unpack('C*',$s[0].$s[1].$s[2].$s[3]))&&$s[1]<(1<<7)?$s[1]:
($s[1]>239&&$s[2]>127&&$s[3]>127&&$s[4]>127?(7&$s[1])<<18|(63&$s[2])<<12|(63&$s[3])<<6|63&$s[4]:
($s[1]>223&&$s[2]>127&&$s[3]>127?(15&$s[1])<<12|(63&$s[2])<<6|63&$s[3]:
($s[1]>193&&$s[2]>127?(31&$s[1])<<6|63&$s[2]:0)));
}

И один быстрыйchr_utf8 Вот : https://stackoverflow.com/a/42510129/7558876

Эта функция выглядит так(accept integer and return a string)

<?php

function chr_utf8($n,$f='C*'){
return $n<(1<<7)?chr($n):($n<1<<11?pack($f,192|$n>>6,1<<7|191&$n):
($n<(1<<16)?pack($f,224|$n>>12,1<<7|63&$n>>6,1<<7|63&$n):
($n<(1<<20|1<<16)?pack($f,240|$n>>18,1<<7|63&$n>>12,1<<7|63&$n>>6,1<<7|63&$n):'')));
}

Пожалуйста, проверьте ссылки, если вы хотите один пример & # x2026;

Кстати: если вы считаете, что на вопрос есть ответ где-то еще в переполнении стека, отметьте его какduplicate вместо цитирования другого ответа.
Ссылка на решение приветствуется, но, пожалуйста, убедитесь, что ваш ответ будет полезен без него:add context around the link поэтому ваши коллеги-пользователи будут иметь некоторое представление о том, что это такое и почему это так, а затем процитировать наиболее релевантную часть страницы, на которую вы ссылаетесь, в случае, если целевая страница недоступна.Answers that are little more than a link may be deleted.

Похожие вопросы