Как преобразовать текстовый блок Unicode в кодовую точку UTF-8 (HEX)?

У меня есть текстовый блок Unicode, например:

ụ
ư
ứ
Ỳ
Ỷ
Ỵ
Đ

Теперь я хочу преобразовать этот оригинальный текстовый блок Unicode в текстовый блок кодовой точки UTF-8 (HEX) (см. столбец шестнадцатеричный UTF-8 на этой странице: https://en.wikipedia.org/wiki/UTF-8), PHP; например:

\xe1\xbb\xa5
\xc6\xb0
\xe1\xbb\xa9
\xe1\xbb\xb2
\xe1\xbb\xb6
\xe1\xbb\xb4
\xc4\x90

Не:

0x1EE5
0x01B0
0x1EE9
0x1EF2
0x1EF6
0x1EF4
0x0110

Есть ли способ сделать это, PHP?


Я прочитал эту тему (PHP: конвертировать кодовую точку юникода в UTF-8). Но он не похож на мой вопрос.


Извините, я мало что знаю о Unicode.

Ответ 1

Я думаю, что вы ищете функцию bin2hex():

Преобразование двоичных данных в шестнадцатеричное представление

И форматируйте, добавив \x к каждому байту (00-FF)

function str_hex_format ($bin) {
  return '\x'.implode('\x', str_split(bin2hex($bin), 2));
}

Для вашего образца:

// utf8 encoded input
$arr = ["ụ","ư","ứ","Ỳ","Ỷ","Ỵ","Đ"];

foreach($arr AS $v)
  echo $v . " => " . str_hex_format($v) . "\n";

Смотрите тест на eval.in (истекает срок действия ссылки)

ụ => \xe1\xbb\xa5
ư => \xc6\xb0
ứ => \xe1\xbb\xa9
Ỳ => \xe1\xbb\xb2
Ỷ => \xe1\xbb\xb6
Ỵ => \xe1\xbb\xb4
Đ => \xc4\x90

Пример декодирования: $str = str_hex_format("ụưứỲỶỴĐ"); echo $str;

\ xe1\Xbb\xa5\xc6\XB0\xe1\Xbb\xA9\xe1\Xbb\XB2\xe1\Xbb\XB6\xe1\Xbb\XB4\XC4\x90

echo hex2bin(str_replace('\x', "", $str));

ụưứỲỶỴĐ


Подробнее о escape-последовательности \x в двойных кавычках см. руководство по php.

Ответ 2

PHP обрабатывает строки как массивы символов, независимо от кодировки. Если вам не нужно разграничивать символы UTF8, то работает что-то вроде этого:

$str='ụưứỲỶỴĐ';
foreach(str_split($str) as $char)
  echo '\x'.str_pad(dechex(ord($char)),'0',2,STR_PAD_LEFT);

Вывод:

\xe1\xbb\xa5\xc6\xb0\xe1\xbb\xa9\xe1\xbb\xb2\xe1\xbb\xb6\xe1\xbb\xb4\xc4\x90

Если вам нужно разграничить символы UTF8 (т.е. с новой строкой), вам понадобится что-то вроде этого:

$str='ụưứỲỶỴĐ';
foreach(array_slice(preg_split('~~u',$str),1,-1) as $UTF8char){ // split before/after every UTF8 character and remove first/last empty string
  foreach(str_split($UTF8char) as $char)
    echo '\x'.str_pad(dechex(ord($char)),'0',2,STR_PAD_LEFT);
  echo "\n"; // delimiter
}

Вывод:

\xe1\xbb\xa5
\xc6\xb0
\xe1\xbb\xa9
\xe1\xbb\xb2
\xe1\xbb\xb6
\xe1\xbb\xb4
\xc4\x90

Это разделяет строку на символы UTF8 с помощью preg_split и u. Поскольку preg_split возвращает пустую строку перед первым символом и пустую строку после последнего символа, нам нужно array_slice первый и последний символы. Это может быть легко изменено для возврата массива, например.

Edit: Более "правильный" способ сделать это:

echo trim(json_encode(utf8_encode('ụưứỲỶỴĐ')),'"');

Ответ 3

Главное, что вам нужно сделать, - сказать PHP правильно интерпретировать входящие символы Юникода. После этого вы можете преобразовать их в UTF-8, а затем, при необходимости, в шестнадцатеричном формате.

Этот фрагмент кода принимает ваш примерный символ в Unicode, преобразует его в UTF-8 и затем сбрасывает шестнадцатеричное представление этих символов.

<?php
// Hex equivalent of "ụưứỲỶỴĐ" in Unicode
$unistr = "\x1E\xE5\x01\xB0\x1E\xE9\x1E\xF2\x1E\xF6\x1E\xF4\x01\x10";
echo " length=" . mb_strlen($unistr, 'UCS-2BE') . "\n";

// Here the key statement, convert from Unicode 16-bit to UTF-8
$utf8str = mb_convert_encoding($unistr, "UTF-8", 'UCS-2BE');
echo $utf8str . "\n";

for($i=0; $i < mb_strlen($utf8str, 'UTF-8'); $i++) {
    $c = mb_substr($utf8str, $i, 1, 'UTF-8');
    $hex = bin2hex($c);
    echo $c . "\t" . $hex . "\t" . preg_replace("/([0-9a-f]{2})/", '\\\\x\\1', $hex) . "\n";
}

?>

Выдает

length=7
ụưứỲỶỴĐ
ụ   e1bba5  \xe1\xbb\xa5
ư   c6b0    \xc6\xb0
ứ   e1bba9  \xe1\xbb\xa9
Ỳ   e1bbb2  \xe1\xbb\xb2
Ỷ   e1bbb6  \xe1\xbb\xb6
Ỵ   e1bbb4  \xe1\xbb\xb4
Đ   c490    \xc4\x90