Menurut artikel Wikipedia , UTF-8 memiliki format ini:
Kode pertama Kode terakhir Bytes Byte 1 Byte 2 Byte 3 Byte 4 point point Digunakan U + 0000 U + 007F 1 0xxxxxxx U + 0080 U + 07FF 2 110xxxxx 10xxxxxx U + 0800 U + FFFF 3 1110xxxx 10xxxxxx 10xxxxxx U + 10000 U + 1FFFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx x berarti bit ini digunakan untuk memilih titik kode.
Ini membuang dua bit pada setiap byte lanjutan dan satu bit pada byte pertama. Mengapa UTF-8 tidak dikodekan seperti berikut ini?
Kode pertama Kode terakhir Bytes Byte 1 Byte 2 Byte 3 point point Digunakan U + 0000 U + 007F 1 0xxxxxxx U + 0080 U + 3FFF 2 10xxxxxx xxxxxxxx U + 0800 U + 1FFFFF 3 110xxxxx xxxxxxxx xxxxxxxx
Ini akan menghemat satu byte ketika titik kode di luar Basic Multilingual Plane atau jika titik kode berada dalam kisaran [U + 800, U + 3FFF].
Mengapa UTF-8 tidak dikodekan dengan cara yang lebih efisien?
Jawaban:
Hal ini dilakukan agar Anda dapat mendeteksi ketika Anda berada di tengah urutan multi-byte. Saat melihat data UTF-8, Anda tahu bahwa jika Anda melihat
10xxxxxx
, bahwa Anda berada di tengah-tengah karakter multibyte, dan harus kembali dalam aliran sampai Anda melihat salah satu0xxxxxx
atau11xxxxxx
. Menggunakan skema Anda, byte 2 atau 3 dapat dengan mudah berakhir dengan pola seperti salah satu0xxxxxxx
atau11xxxxxx
Juga perlu diingat bahwa berapa banyak yang disimpan sepenuhnya bervariasi pada jenis data string apa yang Anda encoding. Untuk sebagian besar teks, bahkan teks Asia, Anda jarang akan melihat empat byte karakter dengan teks normal. Juga, perkiraan naif orang tentang bagaimana teks akan terlihat sering salah. Saya memiliki teks yang dilokalkan untuk UTF-8 yang mencakup string Jepang, Cina, dan Korea, namun sebenarnya bahasa Rusia yang mengambil sebagian besar ruang. (Karena string Asia kita sering memiliki karakter Romawi diselingi untuk nama yang tepat, tanda baca dan semacamnya dan karena kata Cina rata-rata adalah 1-3 karakter sedangkan rata-rata kata Rusia banyak, banyak lagi.)
sumber
Cara resmi memungkinkan decoder tahu ketika itu di tengah-tengah tupel dan ia tahu untuk melewati byte (atau pergi ke belakang) sampai byte dimulai dengan
0
atau11
; ini mencegah nilai-nilai sampah ketika satu byte rusak.sumber
Jawaban singkatnya, proposal Anda tidak membedakan antara byte pertama dan byte lanjutan.
Pola bit di ujung atas byte pertama memberi tahu Anda berapa banyak byte karakter sebenarnya dibangun. Pola-pola ini juga menyediakan beberapa pengenalan kesalahan saat mengurai string. Jika Anda membaca byte pertama dari sebuah karakter dan Anda mendapatkan 10xxxxxx maka Anda tahu bahwa Anda tidak selaras.
sumber
Apa yang belum disebutkan adalah bahwa jika Anda memiliki urutan poin kode yang benar, dan pointer yang dijamin untuk menunjuk ke byte pertama dari titik kode, dengan UTF-8 Anda dapat dengan mudah menemukan pointer ke byte pertama. dari titik kode sebelumnya (lewati semua byte yang dimulai dengan 01xx xxxx). Dengan penyandian Anda, tidak mungkin tanpa berpotensi memeriksa semua byte hingga awal string.
Pertimbangkan urutan (2n + 2) byte
dan
Jika Anda memiliki pointer ke byte pertama dari titik kode pertama setelah urutan ini, Anda harus memeriksa semua byte untuk mengetahui apakah titik kode terakhir adalah 0xxxxxxx atau (10xxxxxx, 0xxxxxxx).
Sebenarnya ada skema pengkodean yang lebih efisien, di mana pergi ke titik kode sebelumnya dapat dilakukan dalam waktu yang konstan, dan pointer ke tengah titik kode dapat diperbaiki. Izinkan kode berikut:
Jika salah satu dari tiga byte sebelumnya adalah ≥ 236 maka itu adalah awal dari urutan 3 byte, karena tidak mungkin ada dua byte seperti itu dalam setiap urutan 3 byte yang valid. Jika tidak, jika salah satu dari dua byte sebelumnya adalah ≥ 128 maka itu adalah awal dari urutan dua byte. Jika tidak, byte sebelumnya adalah byte tunggal <128.
Mencari substring menjadi sedikit lebih sulit. Anda mungkin ingin mengecualikan nol byte sehingga string hanya berisi byte nol jika mengandung titik kode nol.
sumber