Символ Unicode в рядку PHP


164

Це питання виглядає бентежно просто, але я не змогла знайти відповідь.

Який PHP еквівалентний наступному рядку коду C #?

string str = "\u1000";

Цей зразок створює рядок з єдиним символом Unicode, числове числове значення Unicode - 1000 у шістнадцятковій цифрі (4096 у десятковій частині).

Тобто в PHP, як я можу створити рядок з одним символом Unicode, чиє числове значення "Unicode" відоме?



4
@diEcho: це лише для відповідності символів Unicode, але ОП хоче створити для цих символів.
Стефан Гегріг

це може допомогти: randomchaos.com/documents/?source=php_and_unicode
diEcho

Відповіді:


178

Оскільки JSON безпосередньо підтримує \uxxxxсинтаксис, перше, що мені спадає на думку:

$unicodeChar = '\u1000';
echo json_decode('"'.$unicodeChar.'"');

Іншим варіантом буде використання mb_convert_encoding()

echo mb_convert_encoding('က', 'UTF-8', 'HTML-ENTITIES');

або скористайтеся прямим відображенням між UTF-16BE (великий ендіан) та кодовою точкою Unicode:

echo mb_convert_encoding("\x10\x00", 'UTF-8', 'UTF-16BE');

9
JSON - це не JavaScript.
Gumbo

4
@Gumbo: Я знаю, що це не має ніякого значення. Javascript, а також JSON підтримують \uxxxxсинтаксис Unicode, так що ви можете використовувати json_decodeдля роботи над штучно створеним представленням рядків JSON. Я змінив формулювання, хоча щоб це було уточнено.
Стефан Гегріг

3
Гаразд, точне чітке формулювання однієї відповіді на моє запитання: $ str = json_decode ('"\ u1000"'); Дякую.
Телаклаво

Я спробував echo json_decode('\u201B');Який стосується однієї поверненої цитати, однак він не працює, тобто не має жодного результату (навіть якщо на hd
трубку

4
Вам потрібно echo json_decode('"\u201B"');. Подвійні лапки навколо символу unicode є обов'язковими.
Стефан Гегріг

162

PHP 7.0.0 представив синтаксис "Уникнення кодової точки Unicode" .

Тепер можна легко записати символи Unicode, використовуючи подвійне цитування або рядок heredoc , не викликаючи жодної функції.

$unicodeChar = "\u{1000}";

Це можна використовувати так: wordwrap($longLongText, 20, "\u{200B}", true);( нульової ширини це місце )
sanmai

5
Я вважаю, що ОП хотіла цієї відповіді, а не прийнятої відповіді. У будь-якому разі, коли я шукав "Unicode в PHP", це було тому, що я хотів цю відповідь, а не прийняту відповідь. Можливо, "\ u {abcd}" не існувало, коли це питання було вперше задано. Якщо так, прийняту відповідь зараз слід перемістити.
Адам Чалкрафт

23

Цікаво, чому ніхто ще не згадав про це, але ви можете зробити майже еквівалентну версію, використовуючи послідовності втечі в подвійних цитованих рядках :

\x[0-9A-Fa-f]{1,2}

Послідовність символів, що відповідає регулярному виразу, є символом у шістнадцятковій нотації.

Приклад ASCII:

<?php
    echo("\x48\x65\x6C\x6C\x6F\x20\x57\x6F\x72\x6C\x64\x21");
?>

Привіт Світ!

Отже, для вашого випадку все, що вам потрібно зробити, - це $str = "\x30\xA2";. Але це байти , а не символи. Представлення байтів кодової точки Unicode збігається з великим ендіаном UTF-16, тому ми могли би роздрукувати його безпосередньо як таке:

<?php
    header('content-type:text/html;charset=utf-16be');
    echo("\x30\xA2");
?>

Якщо ви використовуєте інше кодування, вам потрібно буде змінити байти відповідно (в основному це робиться з бібліотекою, хоча можливо і вручну).

Приклад UTF-16: маленький ендіанець:

<?php
    header('content-type:text/html;charset=utf-16le');
    echo("\xA2\x30");
?>

Приклад UTF-8:

<?php
    header('content-type:text/html;charset=utf-8');
    echo("\xE3\x82\xA2");
?>

Є також packфункція, але ви можете сподіватися, що вона буде повільною.


Ідеально підходить, коли копіювання / вставлення символу кулі (\ xE2 \ x80 \ xA2) може призвести до помилки кодування UTF-8 у вихідному документі. Дякую.
jimp

21

PHP не знає цих послідовностей виходу Unicode. Але оскільки невідомі послідовності втечі залишаються незмінними, ви можете написати власну функцію, яка перетворює такі послідовності виходу Unicode:

function unicodeString($str, $encoding=null) {
    if (is_null($encoding)) $encoding = ini_get('mbstring.internal_encoding');
    return preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/u', create_function('$match', 'return mb_convert_encoding(pack("H*", $match[1]), '.var_export($encoding, true).', "UTF-16BE");'), $str);
}

Або з анонімним виразом функції замість create_function:

function unicodeString($str, $encoding=null) {
    if (is_null($encoding)) $encoding = ini_get('mbstring.internal_encoding');
    return preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/u', function($match) use ($encoding) {
        return mb_convert_encoding(pack('H*', $match[1]), $encoding, 'UTF-16BE');
    }, $str);
}

Її використання:

$str = unicodeString("\u1000");

10
html_entity_decode('&#x30a8;', 0, 'UTF-8');

Це теж працює. Однак рішення json_decode () набагато швидше (приблизно в 50 разів).


Простий, елегантний, простий і повністю безпечний метод. +10
andreszs


3

Як зазначають інші, PHP 7 вводить підтримку \uсинтаксису Unicode безпосередньо.

Як також зазначають інші, єдиний спосіб отримати значення рядка з будь-якого чуйного опису символів Unicode в PHP - це перетворення його з чогось іншого (наприклад, JSON-синтаксичний аналіз, HTML-аналіз чи інша форма). Але це відбувається за рахунок експлуатаційних витрат.

Однак є ще один варіант. Ви можете кодувати символу безпосередньо в PHP, використовуючи \xбінарне сканування. \xСинтаксис втечу також підтримується в PHP 5 .

Це особливо корисно, якщо ви волієте не вводити персонаж прямо в рядку через його природну форму. Наприклад, якщо це невидимий контрольний символ або інший важко виявити пробіл.

По-перше, доказний приклад:

// Unicode Character 'HAIR SPACE' (U+200A)
$htmlEntityChar = "&#8202;";
$realChar = html_entity_decode($htmlEntityChar);
$phpChar = "\xE2\x80\x8A";
echo 'Proof: ';
var_dump($realChar === $phpChar); // bool(true)

Зауважте, що, як згадує Пак’єр в іншій відповіді, цей двійковий код унікальний для конкретного кодування символів. У наведеному вище прикладі \xE2\x80\x8Aє двійкове кодування для U + 200A в UTF-8.

Наступне питання, як ви отримаєте від U+200Aдо \xE2\x80\x8A?

Нижче наведено скрипт PHP для створення послідовності запуску для будь-якого символу, заснованого на рядку JSON, HTML-суті або будь-якому іншому методі, як тільки ви матимете його як рідну рядок.

function str_encode_utf8binary($str) {
    /** @author Krinkle 2018 */
    $output = '';
    foreach (str_split($str) as $octet) {
        $ordInt = ord($octet);
        // Convert from int (base 10) to hex (base 16), for PHP \x syntax
        $ordHex = base_convert($ordInt, 10, 16);
        $output .= '\x' . $ordHex;
    }
    return $output;
}

function str_convert_html_to_utf8binary($str) {
    return str_encode_utf8binary(html_entity_decode($str));
}
function str_convert_json_to_utf8binary($str) {
    return str_encode_utf8binary(json_decode($str));
}

// Example for raw string: Unicode Character 'INFINITY' (U+221E)
echo str_encode_utf8binary('∞') . "\n";
// \xe2\x88\x9e

// Example for HTML: Unicode Character 'HAIR SPACE' (U+200A)
echo str_convert_html_to_utf8binary('&#8202;') . "\n";
// \xe2\x80\x8a

// Example for JSON: Unicode Character 'HAIR SPACE' (U+200A)
echo str_convert_json_to_utf8binary('"\u200a"') . "\n";
// \xe2\x80\x8a

0
function unicode_to_textstring($str){

    $rawstr = pack('H*', $str);

    $newstr =  iconv('UTF-16BE', 'UTF-8', $rawstr);
    return $newstr;
}

$ msg = '67714eac99c500200054006f006b0079006f002000530074006100740069006f006e003a0020';

echo unicode_to_textstring ($ str);

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.