Bagaimana cara kerja "pengkodean lebar-variabel" UTF-8?

110

Standar unicode memiliki cukup poin kode di dalamnya sehingga Anda memerlukan 4 byte untuk menyimpan semuanya. Itulah yang dilakukan pengkodean UTF-32. Namun pengkodean UTF-8 entah bagaimana meremasnya ke dalam ruang yang jauh lebih kecil dengan menggunakan sesuatu yang disebut "pengkodean lebar-variabel".

Faktanya, ini berhasil mewakili 127 karakter pertama US-ASCII hanya dalam satu byte yang terlihat persis seperti ASCII asli, sehingga Anda dapat menafsirkan banyak teks ascii seolah-olah UTF-8 tanpa melakukan apa pun padanya. Trik rapi. Jadi bagaimana cara kerjanya?

Saya akan bertanya dan menjawab pertanyaan saya sendiri di sini karena saya baru saja membaca sedikit untuk mengetahuinya dan saya pikir ini akan menghemat waktu orang lain. Ditambah mungkin seseorang bisa mengoreksi saya jika saya salah.

dsimard
sumber
8
Straight Unicode tidak memerlukan 32 bit untuk menyandikan semua titik kodenya. Mereka pernah mengklaim bahwa banyak poin kode yang mungkin, tetapi setelah UTF-8 lepas landas, mereka dengan sengaja membatasi diri pada 21 bit, sehingga UTF-8 tidak akan pernah melebihi 4 byte per karakter. Unicode saat ini hanya membutuhkan 17 bit untuk menampung semua kemungkinan titik kode. Tanpa batasan ini, UTF-8 bisa mencapai 6 byte per karakter.
Warren Young
@Warren: sebagian besar akurat, tetapi Unicode adalah kode 21-bit (U + 0000 hingga U + 10FFFF).
Jonathan Leffler
2
@Warren: UTF-8 terbatas 4-byte dapat mendukung hingga U + 1FFFFF. Pembatasan U + 10FFFF dibuat demi UTF-16.
dan04
@ dan04 Apakah kami memiliki penjelasan yang mudah tentang bagaimana pembatasan ini dibatasi pada U + 10FFFF oleh UTF-16? Akan menyenangkan mengetahui lebih banyak tentang ini.
A-letubby
@ A-letubby: Karena kode "pengganti" UTF-16 dialokasikan sedemikian rupa sehingga ada 1024 pengganti prospek dan 1024 pengganti jejak (dan mereka hanya dapat digunakan berpasangan), untuk membuat 2 ^ 20 (sekitar satu juta) karakter tambahan tersedia di luar BMP. Ditambahkan ke 2 ^ 16 karakter yang tersedia di BMP, ini memungkinkan 0x110000 karakter.
dan04

Jawaban:

129

Setiap byte dimulai dengan beberapa bit yang memberi tahu Anda apakah itu titik kode byte tunggal, titik kode multi-byte, atau kelanjutan dari titik kode multi-byte. Seperti ini:

0xxx xxxx    A single-byte US-ASCII code (from the first 127 characters)

Titik kode multi-byte masing-masing dimulai dengan beberapa bit yang pada dasarnya mengatakan "hei, Anda juga perlu membaca byte berikutnya (atau dua, atau tiga) untuk mengetahui siapa saya." Mereka:

110x xxxx    One more byte follows
1110 xxxx    Two more bytes follow
1111 0xxx    Three more bytes follow

Akhirnya, semua byte yang mengikuti kode awal tersebut terlihat seperti ini:

10xx xxxx    A continuation of one of the multi-byte characters

Karena Anda dapat mengetahui jenis byte yang Anda lihat dari beberapa bit pertama, bahkan jika ada sesuatu yang rusak di suatu tempat, Anda tidak kehilangan seluruh urutannya.

dsimard
sumber
14
Ada lebih banyak cerita daripada itu - karena pengkodean harus menjadi pengkodean sesingkat mungkin untuk karakter, yang pada akhirnya berarti bahwa byte 0xC0 dan 0xC1 tidak dapat muncul di UTF-8, misalnya; dan, pada kenyataannya, tidak bisa 0xF5..0xFF. Lihat UTF-8 FAQ di unicode.org/faq/utf_bom.html , atau unicode.org/versions/Unicode5.2.0/ch03.pdf
Jonathan Leffler
2
Mengapa tidak bisa menggunakan hanya satu karakter untuk diucapkan next char is continuation? Jika kita mendapat karakter 3 byte maka akan seperti:, 1xxxxxxx 1xxxxxxx 0xxxxxxxjadi lebih sedikit ruang yang terbuang.
9
@ Soaku itu membuat UTF-8 menjadi apa yang disebut kode "sinkronisasi diri". Ini berarti jika karena kesalahan bagian dari urutan hilang, maka dimungkinkan untuk mendeteksinya dan membuang apa pun yang rusak. Jika Anda membaca byte yang dimulai dengan 10xx, dan tidak ada byte "mulai" sebelumnya, Anda dapat membuangnya karena tidak ada artinya. Jika Anda memiliki sistem seperti yang Anda jelaskan, dan salah satu byte pertama hilang, Anda mungkin akan mendapatkan karakter valid yang berbeda tanpa indikasi kesalahan apa pun. Ini juga akan memudahkan untuk menemukan karakter valid berikutnya, serta mengoreksi byte "lanjutan" yang hilang.
htmlcoderexe
9

RFC3629 - UTF-8, format transformasi ISO 10646 adalah otoritas akhir di sini dan memiliki semua penjelasannya.

Singkatnya, beberapa bit di setiap byte dari urutan 1-ke-4-byte berenkode UTF-8 yang mewakili satu karakter digunakan untuk menunjukkan apakah itu byte tambahan, byte utama, dan jika demikian, berapa banyak byte yang mengikuti. Bit yang tersisa berisi payload.

azheglov.dll
sumber
1
Ummmm, bodohnya saya, saya pikir Unicode Standard adalah otoritas terakhir pada UTF-8
John Machin
6
Standar Unicode mendefinisikan Unicode itu sendiri. Itu tidak menentukan berbagai metode, hari ini dan masa depan, yang dapat digunakan untuk menyandikan teks unicode untuk berbagai tujuan (seperti penyimpanan dan transportasi). UTF-8 adalah salah satu metode tersebut dan referensi di atas adalah ke dokumen yang mendefinisikannya.
azheglov
1
RFC3629, halaman 3, bagian 3. mengatakan "UTF-8 didefinisikan oleh Unicode Standard".
John Machin
Mengejar tautan di unicode.org membawa saya ke bagian 3.9 dari Standar Unicode dan secara khusus definisi D92 (dan juga secara tangensial D86). Saya tidak tahu sejauh mana tautan ini akan berguna ketika versi baru dirilis tetapi saya akan membayangkan bahwa mereka ingin menjaga bagian dan pengidentifikasi definisi stabil di semua versi.
tripleee
4

UTF-8 adalah sistem lain untuk menyimpan string poin kode Unicode Anda, angka U + ajaib itu, dalam memori menggunakan 8 bit byte. Dalam UTF-8, setiap titik kode dari 0-127 disimpan dalam satu byte. Hanya poin kode 128 ke atas yang disimpan menggunakan 2, 3, hingga 6 byte.

Kutipan dari The Absolute Minimum Setiap Pengembang Perangkat Lunak Sepenuhnya, Secara Positif Harus Tahu Tentang Unicode dan Kumpulan Karakter (Tanpa Alasan!)

Andrew
sumber
Itu artikel yang bagus, tapi sepertinya Joel salah tentang panjang maksimum urutannya; halaman Wikipedia hanya menampilkan 1..4 byte per karakter.
bersantai
4
Seperti yang saya katakan di atas, ketika UTF-8 pertama kali dibuat, Unicode mengklaim hingga 32-bit untuk poin kode, bukan karena mereka benar-benar membutuhkannya, hanya karena 32-bit adalah nilai yang nyaman dan mereka sudah melewati batas batas sebelumnya dari karakter 16-bit. Setelah UTF-8 terbukti populer, mereka memilih untuk selamanya membatasi jumlah maksimum poin kode menjadi 2 ^ 21, yang menjadi nilai terbesar yang dapat Anda encode dengan 4 byte dari skema UTF-8. Masih ada kurang dari 2 ^ 17 karakter di Unicode, jadi kita dapat melipatgandakan jumlah karakter di Unicode dengan skema baru ini lebih dari empat kali lipat.
Warren Young
Ok tapi bukan penjelasan yang ditanyakan OP.
Nishant
2
Ini tidak menjawab pertanyaan itu.
Koray Tugay