Karakter Unicode dalam string PHP

164

Pertanyaan ini terlihat sangat memalukan, tetapi saya belum dapat menemukan jawaban.

Berapakah nilai PHP yang setara dengan baris kode C # berikut?

string str = "\u1000";

Sampel ini membuat string dengan karakter Unicode tunggal yang "nilai numerik Unicode" adalah 1000 dalam heksadesimal (4096 dalam desimal).

Yaitu, di PHP, bagaimana saya bisa membuat string dengan karakter Unicode tunggal yang "nilai numerik Unicode" diketahui?

Telaclavo
sumber
4
@diEcho: itu hanya untuk mencocokkan karakter Unicode, tetapi OP ingin membuat karakter tersebut.
Stefan Gehrig

Jawaban:

178

Karena JSON secara langsung mendukung \uxxxxsintaks, hal pertama yang muncul di pikiran saya adalah:

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

Pilihan lain adalah menggunakan mb_convert_encoding()

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

atau manfaatkan pemetaan langsung antara UTF-16BE (big endian) dan titik kode Unicode:

echo mb_convert_encoding("\x10\x00", 'UTF-8', 'UTF-16BE');
Stefan Gehrig
sumber
9
JSON bukan JavaScript.
Gumbo
4
@ Gumbo: Saya tahu itu, tetapi tidak ada bedanya di sini. Javascript dan JSON mendukung \uxxxxsintaks Unicode sehingga Anda dapat menggunakannya json_decodeuntuk bekerja pada representasi string JSON yang dibuat secara artifisial. Saya mengubah kata-katanya untuk diklarifikasi.
Stefan Gehrig
3
Oke, jadi rumusan ketat satu jawaban untuk pertanyaan saya adalah: $ str = json_decode ('"\ u1000"'); Terima kasih.
Telaclavo
Saya mencoba echo json_decode('\u201B');Yang merujuk pada satu kutipan yang dikembalikan Namun tidak berfungsi, artinya tidak ada output (bahkan jika disalurkan ke hd)
hek2mgl
4
Kamu butuh echo json_decode('"\u201B"');. Kutipan ganda di sekitar simbol unicode adalah wajib.
Stefan Gehrig
162

PHP 7.0.0 telah memperkenalkan sintaks "Unicode codepoint escape" .

Sekarang dimungkinkan untuk menulis karakter Unicode dengan mudah dengan menggunakan string yang dikutip ganda atau heredoc , tanpa memanggil fungsi apa pun.

$unicodeChar = "\u{1000}";
Lubang hitam
sumber
Ini dapat digunakan seperti ini: wordwrap($longLongText, 20, "\u{200B}", true);( ruang nol-lebar itu)
sanmai
5
Saya percaya OP menginginkan jawaban ini, bukan jawaban yang diterima. Bagaimanapun, ketika saya mencari "Unicode di PHP", itu karena saya menginginkan jawaban ini, bukan jawaban yang diterima. Mungkin "\ u {abcd}" tidak ada saat pertanyaan ini pertama kali ditanyakan. Jika demikian, jawaban yang diterima sekarang harus dipindahkan.
Adam Chalcraft
23

Saya bertanya-tanya mengapa belum ada yang menyebutkan ini, tetapi Anda dapat melakukan versi yang hampir setara menggunakan urutan melarikan diri dalam string dikutip ganda :

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

Urutan karakter yang cocok dengan ekspresi reguler adalah karakter dalam notasi heksadesimal.

Contoh ASCII:

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

Halo Dunia!

Jadi untuk kasus Anda, yang perlu Anda lakukan adalah $str = "\x30\xA2";. Tapi ini byte , bukan karakter. Representasi byte dari Unicode codepoint bertepatan dengan UTF-16 big endian, jadi kita bisa mencetaknya secara langsung seperti:

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

Jika Anda menggunakan penyandian yang berbeda, Anda harus mengubah byte yang sesuai (kebanyakan dilakukan dengan pustaka, meskipun mungkin dengan tangan juga).

UTF-16 contoh kecil endian:

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

Contoh UTF-8:

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

Ada juga packfungsinya, tetapi Anda bisa mengharapkannya lambat.

Pacerier
sumber
Sempurna untuk ketika menyalin / menempel karakter bullet (\ xE2 \ x80 \ xA2) dapat mengakibatkan kesalahan pengkodean UTF-8 dalam dokumen sumber. Terima kasih.
jimp
21

PHP tidak tahu urutan pelepasan Unicode ini. Tetapi karena urutan pelarian yang tidak diketahui tetap tidak terpengaruh, Anda dapat menulis fungsi Anda sendiri yang mengubah urutan pelarian Unicode tersebut:

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

Atau dengan ekspresi fungsi anonim alih-alih 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);
}

Penggunaannya:

$str = unicodeString("\u1000");
Gumbo
sumber
10
html_entity_decode('&#x30a8;', 0, 'UTF-8');

Ini juga berfungsi. Namun solusi json_decode () jauh lebih cepat (sekitar 50 kali).

flori
sumber
Metode sederhana, elegan, mudah dan benar-benar aman. +10
andreszs
7

Coba Portable UTF-8 :

$str = utf8_chr( 0x1000 );
$str = utf8_chr( '\u1000' );
$str = utf8_chr( 4096 );

Semua bekerja dengan cara yang persis sama. Anda bisa mendapatkan codepoint karakter dengan utf8_ord(). Baca lebih lanjut tentang Portable UTF-8 .

Hamid Sarfraz
sumber
3

Seperti yang disebutkan oleh yang lain, PHP 7 memperkenalkan dukungan untuk \usintaks Unicode secara langsung.

Seperti yang juga disebutkan oleh orang lain, satu-satunya cara untuk mendapatkan nilai string dari deskripsi karakter Unicode yang masuk akal di PHP, adalah dengan mengonversinya dari sesuatu yang lain (mis. Parsing JSON, parsing HTML atau bentuk lain). Tetapi ini datang dengan biaya kinerja run-time.

Namun, ada satu opsi lain. Anda dapat menyandikan karakter secara langsung di PHP dengan \xbinary escaping. The \xsintaks melarikan diri juga didukung dalam PHP 5 .

Ini sangat berguna jika Anda memilih untuk tidak memasukkan karakter secara langsung dalam string melalui bentuk aslinya. Misalnya, jika itu adalah karakter kontrol yang tidak terlihat, atau sulit lainnya untuk mendeteksi spasi putih.

Pertama, contoh bukti:

// 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)

Perhatikan bahwa, seperti yang disebutkan oleh Pacerier dalam jawaban lain, kode biner ini unik untuk pengkodean karakter tertentu. Dalam contoh di atas, \xE2\x80\x8Aadalah pengkodean biner untuk U + 200A di UTF-8.

Pertanyaan berikutnya adalah, bagaimana Anda dapatkan dari U+200Ake \xE2\x80\x8A?

Di bawah ini adalah skrip PHP untuk menghasilkan urutan escape untuk setiap karakter, berdasarkan pada string JSON, entitas HTML, atau metode lain setelah Anda memilikinya sebagai string asli.

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
Timo Tijhof
sumber
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);

chings228
sumber