Преобразование ссылки Unicode в символ UTF-8 в PHP с помощью mbstring - PullRequest
1 голос
/ 16 ноября 2011

У меня есть набор данных внутри базы данных, который был введен с символами Unicode, но они были интерпретированы как строка. То есть там, где должен быть апостроф У меня на самом деле есть \u2019

Так что теперь мне нужно преобразовать это в его символьное представление, которое . Во-первых, довольно просто изменить строку на версию объекта: ’, затем мне нужно превратить ее в правильную многобайтовую строку UTF-8.

Я пытался сделать это несколькими способами; на моем локальном сервере я могу извлечь символы с помощью функции preg_match, а затем передать каждый из них следующей функции:

mb_convert_encoding($string, "UTF-8", "HTML-ENTITIES");

Звучит вполне разумно и работает без проблем. Отключение кодировки UTF-8 в браузере показывает, что оно фактически преобразуется в ’ при чтении в кодировке браузера по умолчанию.

Тем не менее, точно такой же код при запуске в моей производственной среде выдает страшное поле «отсутствующий символ» при визуализации как UTF-8. Выключив UTF-8, вы получите поток байтов, который будет отображаться как ò°‘£. Похоже, что он выводит 4 байта, а не 3, я не знаю, насколько это актуально, так как я плохо разбираюсь в кодировке символов.

Я предполагаю, что проблема связана с моими настройками mbstring. Вот настройки mbstring с моего локального сервера:

Multibyte Support   enabled
Multibyte string engine libmbfl
HTTP input encoding translation disabled
Multibyte (japanese) regex support  enabled
Multibyte regex (oniguruma) version 4.7.1
mbstring.detect_order   no value    no value
mbstring.encoding_translation   Off Off
mbstring.func_overload  0   0
mbstring.http_input auto    auto
mbstring.http_output    UTF-8   UTF-8
mbstring.http_output_conv_mimetypes ^(text/|application/xhtml\+xml)^(text/|application/xhtml\+xml)
mbstring.internal_encoding  UTF-8   UTF-8
mbstring.language   neutral neutral
mbstring.strict_detection   Off Off
mbstring.substitute_character   no value    no value

В производственной среде есть несколько отличий:

Multibyte Support   enabled
Multibyte string engine libmbfl
Multibyte (japanese) regex support  enabled
Multibyte regex (oniguruma) version 3.7.1
mbstring.detect_order   no value    no value
mbstring.encoding_translation   Off Off
mbstring.func_overload  0   0
mbstring.http_input auto    auto
mbstring.http_output    UTF-8   UTF-8
mbstring.internal_encoding  UTF-8   UTF-8
mbstring.language   neutral neutral
mbstring.strict_detection   Off Off
mbstring.substitute_character   no value    no value

Кто-нибудь видит, что я делаю не так?

Ответы [ 2 ]

1 голос
/ 24 февраля 2017

Я думаю, что вы ищете, это многобайтовые версии ord и chr.

Для этого я написал polyfill:

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');
        }
    }
}

Демо

echo "\nGet string from numeric DEC value\n";
var_dump(mb_chr(25105));
var_dump(mb_chr(22909));

echo "\nGet string from numeric HEX value\n";
var_dump(mb_chr(0x6211));
var_dump(mb_chr(0x597D));

echo "\nGet numeric value of character as DEC int\n";
var_dump(mb_ord('我'));
var_dump(mb_ord('好'));

echo "\nGet numeric value of character as HEX string\n";
var_dump(dechex(mb_ord('我')));
var_dump(dechex(mb_ord('好')));

Выход:

Get string from numeric DEC value
string(3) "我"
string(3) "好"

Get string from numeric HEX value
string(3) "我"
string(3) "好"

Get numeric value of character as DEC string
int(25105)
int(22909)

Get numeric value of character as HEX string
string(4) "6211"
string(4) "597d"
0 голосов
/ 28 декабря 2011

Посмотрите, может ли это вам помочь: hex2ascii и ascii2hex

ДОБАВЛЕНО 19-19-2012:

function ascii2hex($ascii)
{
    $hex = '';
    for ($i = 0; $i < strlen($ascii); $i++)
    {
        $byte = strtoupper(dechex(ord($ascii{$i})));
        $byte = str_repeat('0', 2 - strlen($byte)).$byte;
        $hex .= $byte." ";
    }
    return $hex;
}

function hex2ascii($hex)
{
    $ascii = '';
    $hex = str_replace(" ", "", $hex);
    for($i = 0; $i < strlen($hex); $i = $i+2)
        $ascii .= chr(hexdec(substr($hex, $i, 2)));

    return($ascii);
}
...