Apakah UTF-16 memiliki lebar tetap atau lebar variabel? Saya mendapat hasil berbeda dari sumber berbeda:
Dari http://www.tbray.org/ongoing/When/200x/2003/04/26/UTF :
UTF-16 menyimpan karakter Unicode dalam potongan enam belas-bit.
Dari http://en.wikipedia.org/wiki/UTF-16/UCS-2 :
UTF-16 (16-bit Unicode Transformation Format) adalah pengkodean karakter untuk Unicode yang mampu mengkodekan angka 1.112.064 [1] (disebut titik kode) dalam ruang kode Unicode dari 0 hingga 0x10FFFF. Ini menghasilkan hasil panjang variabel dari satu atau dua unit kode 16-bit per titik kode.
Dari sumber pertama
UTF-8 juga memiliki keunggulan bahwa unit encoding adalah byte, sehingga tidak ada masalah pemesanan byte.
Mengapa UTF-8 tidak memiliki masalah byte-order? Lebar variabel, dan satu karakter dapat berisi lebih dari satu byte, jadi saya pikir byte-order masih bisa menjadi masalah?
Terima kasih dan salam!
sumber
Jawaban:
Anda tampaknya salah paham tentang masalah endian. Berikut ringkasan singkatnya.
Bilangan bulat 32-bit membutuhkan 4 byte. Sekarang, kita tahu urutan logis dari byte ini. Jika Anda memiliki integer 32-bit, Anda bisa mendapatkan byte tinggi ini dengan kode berikut:
Semuanya baik dan bagus. Di mana masalahnya dimulai adalah bagaimana berbagai perangkat keras menyimpan dan mengambil bilangan bulat dari memori.
Dalam urutan Big Endian, sepotong memori 4 byte yang Anda baca sebagai integer 32-bit akan dibaca dengan byte pertama menjadi byte tinggi:
Dalam urutan Little Endian, sepotong memori 4 byte yang Anda baca sebagai integer 32-bit akan dibaca dengan byte pertama menjadi byte rendah :
Jika Anda memiliki pointer ke pointer ke nilai 32-bit, Anda bisa melakukan ini:
Menurut C / C ++, hasil ini tidak terdefinisi. Itu bisa 0x81. Atau bisa juga 0x32. Secara teknis, itu bisa mengembalikan apa pun, tetapi untuk sistem nyata, itu akan mengembalikan satu atau yang lain.
Jika Anda memiliki pointer ke alamat memori, Anda dapat membaca alamat itu sebagai nilai 32-bit, nilai 16-bit, atau nilai 8-bit. Pada mesin big endian, pointer menunjuk ke byte tinggi; pada mesin endian kecil, pointer menunjuk ke byte rendah.
Perhatikan bahwa ini semua tentang membaca dan menulis ke / dari memori. Ini tidak ada hubungannya dengan kode C / C ++ internal. Versi pertama dari kode, yang tidak dinyatakan sebagai C / C ++ tidak terdefinisi, akan selalu berfungsi untuk mendapatkan byte tinggi.
Masalahnya adalah ketika Anda mulai membaca stream byte. Seperti dari suatu file.
Nilai 16-bit memiliki masalah yang sama dengan nilai 32-bit; mereka hanya memiliki 2 byte, bukan 4. Oleh karena itu, file dapat berisi nilai 16-bit yang disimpan dalam urutan endian besar atau kecil.
UTF-16 didefinisikan sebagai urutan nilai 16-bit . Secara efektif, itu adalah
uint16_t[]
. Setiap unit kode individu memiliki nilai 16-bit. Oleh karena itu, untuk memuat UTF-16 dengan benar, Anda harus tahu apa kegunaan data itu.UTF-8 didefinisikan sebagai urutan nilai 8-bit . Itu adalah
uint8_t[]
. Setiap unit kode individu berukuran 8-bit: satu byte.Sekarang, baik UTF-16 dan UTF-8 memungkinkan untuk beberapa unit kode (nilai 16-bit atau 8-bit) untuk bergabung bersama untuk membentuk titik kode Unicode ("karakter", tapi itu bukan istilah yang benar; itu adalah penyederhanaan ). The rangka unit kode ini yang membentuk codepoint sebuah ditentukan oleh UTF-16 dan UTF-8 encoding.
Saat memproses UTF-16, Anda membaca nilai 16-bit, melakukan konversi endian apa pun yang diperlukan. Kemudian, Anda mendeteksi apakah itu pasangan pengganti; jika ya, maka Anda membaca nilai 16-bit lain, menggabungkan keduanya, dan dari sana, Anda mendapatkan nilai titik kode Unicode.
Saat memproses UTF-8, Anda membaca nilai 8-bit. Konversi endian tidak dimungkinkan, karena hanya ada satu byte. Jika byte pertama menunjukkan urutan multi-byte, maka Anda membaca beberapa jumlah byte, seperti yang ditentukan oleh urutan multi-byte. Setiap byte individu adalah byte dan karenanya tidak memiliki konversi endian. para rangka ini byte dalam urutan, seperti urutan pasangan pengganti di UTF-16, didefinisikan oleh UTF-8.
Jadi tidak ada masalah endian dengan UTF-8.
sumber
Jawaban Jeremy Banks benar sejauh ini, tetapi tidak membahas pemesanan byte.
Ketika Anda menggunakan UTF-16, sebagian besar mesin terbang disimpan menggunakan kata dua-byte - tetapi ketika kata itu disimpan dalam file disk, urutan apa yang Anda gunakan untuk menyimpan byte konstituen?
Sebagai contoh, mesin terbang CJK (Cina) untuk kata "air" memiliki pengkodean UTF-16 dalam heksadesimal 6C34. Ketika Anda menulis itu sebagai dua byte ke disk, apakah Anda menuliskannya sebagai "big-endian" (dua byte tersebut adalah 6C 34)? Atau apakah Anda menulisnya sebagai "little-endian (dua byte adalah 34 6C)?
Dengan UTF-16, kedua pemesanan adalah sah, dan Anda biasanya menunjukkan yang mana dari file tersebut dengan membuat kata pertama dalam file menjadi Byte Order Mark (BOM), yang untuk pengkodean big-endian adalah FE FF, dan untuk little-endian encoding adalah FF FE.
UTF-32 memiliki masalah yang sama, dan solusi yang sama.
UTF-8 tidak memiliki masalah ini, karena itu panjang variabel, dan Anda secara efektif menulis urutan byte glyph seolah-olah itu adalah little-endian. Misalnya, huruf "P" selalu dikodekan menggunakan satu byte - 80 - dan karakter pengganti selalu dikodekan menggunakan dua byte FF FD dalam urutan itu.
Beberapa program menempatkan indikator tiga byte (EF BB BF) pada awal file UTF-8, dan itu membantu membedakan UTF-8 dari pengkodean serupa seperti ASCII, tetapi itu tidak terlalu umum kecuali pada MS Windows.
sumber