Apa perbedaan antara UTF-8, UTF-16, dan UTF-32?
Saya mengerti bahwa mereka semua akan menyimpan Unicode, dan masing-masing menggunakan jumlah byte yang berbeda untuk mewakili karakter. Apakah ada keuntungan memilih satu dari yang lain?
Apa perbedaan antara UTF-8, UTF-16, dan UTF-32?
Saya mengerti bahwa mereka semua akan menyimpan Unicode, dan masing-masing menggunakan jumlah byte yang berbeda untuk mewakili karakter. Apakah ada keuntungan memilih satu dari yang lain?
Jawaban:
UTF-8 memiliki keunggulan dalam kasus di mana karakter ASCII mewakili mayoritas karakter dalam blok teks, karena UTF-8 mengkodekan ini menjadi 8 bit (seperti ASCII). Juga menguntungkan karena file UTF-8 yang hanya berisi karakter ASCII memiliki penyandian yang sama dengan file ASCII.
UTF-16 lebih baik di mana ASCII tidak dominan, karena menggunakan 2 byte per karakter, terutama. UTF-8 akan mulai menggunakan 3 byte atau lebih untuk karakter tingkat tinggi di mana UTF-16 tetap hanya 2 byte untuk sebagian besar karakter.
UTF-32 akan mencakup semua karakter yang mungkin dalam 4 byte. Ini membuatnya sangat kembung. Saya tidak bisa memikirkan keuntungan apa pun untuk menggunakannya.
Pendeknya:
wchar_t
default hingga 4 byte. gcc memiliki opsi -fshort-wchar
yang mengurangi ukuran menjadi 2 byte, tetapi memecah kompatibilitas biner dengan std libs.
UTF-8 adalah variabel 1 hingga 4 byte.
UTF-16 adalah variabel 2 atau 4 byte.
UTF-32 diperbaiki 4 byte.
Catatan: UTF-8 dapat membutuhkan 1 hingga 6 byte dengan konvensi terbaru: https://lists.gnu.org/archive/html/help-flex/2005-01/msg00030.html
Unicode mendefinisikan satu set karakter besar tunggal, menetapkan satu nilai integer unik untuk setiap simbol grafis (yang merupakan penyederhanaan utama, dan sebenarnya tidak benar, tetapi cukup dekat untuk keperluan pertanyaan ini). UTF-8/16/32 hanyalah beberapa cara berbeda untuk menyandikan ini.
Singkatnya, UTF-32 menggunakan nilai 32-bit untuk setiap karakter. Itu memungkinkan mereka untuk menggunakan kode lebar-tetap untuk setiap karakter.
UTF-16 menggunakan 16-bit secara default, tetapi itu hanya memberi Anda 65k kemungkinan karakter, yang mana tidak cukup dekat untuk set Unicode penuh. Jadi beberapa karakter menggunakan pasangan nilai 16-bit.
Dan UTF-8 menggunakan nilai-nilai 8-bit secara default, yang berarti bahwa 127 nilai pertama adalah karakter byte-lebar tetap-bit (bit paling signifikan digunakan untuk menandakan bahwa ini adalah awal dari urutan multi-byte, meninggalkan 7 bit untuk nilai karakter aktual). Semua karakter lain dikodekan sebagai urutan hingga 4 byte (jika ingatanku).
Dan itu membawa kita pada keuntungan. Setiap karakter ASCII secara langsung kompatibel dengan UTF-8, jadi untuk memutakhirkan aplikasi lawas, UTF-8 adalah pilihan umum dan jelas. Dalam hampir semua kasus, itu juga akan menggunakan memori paling sedikit. Di sisi lain, Anda tidak dapat membuat jaminan tentang lebar karakter. Lebar mungkin 1, 2, 3 atau 4 karakter, yang membuat manipulasi string menjadi sulit.
UTF-32 bertolak belakang, ia menggunakan memori terbanyak (masing-masing karakter memiliki lebar 4 byte tetap), tetapi di sisi lain, Anda tahu bahwa setiap karakter memiliki panjang yang tepat ini, sehingga manipulasi string menjadi jauh lebih sederhana. Anda dapat menghitung jumlah karakter dalam string hanya dari panjang dalam byte string. Anda tidak dapat melakukannya dengan UTF-8.
UTF-16 adalah kompromi. Ini memungkinkan sebagian besar karakter masuk ke dalam nilai 16-bit dengan lebar tetap. Jadi selama Anda tidak memiliki simbol Cina, not musik atau lainnya, Anda dapat mengasumsikan bahwa setiap karakter memiliki lebar 16 bit. Ini menggunakan lebih sedikit memori daripada UTF-32. Tetapi dalam beberapa hal "yang terburuk dari kedua dunia". Hampir selalu menggunakan lebih banyak memori daripada UTF-8, dan masih tidak menghindari masalah yang mengganggu UTF-8 (karakter panjang variabel).
Akhirnya, sering kali membantu hanya dengan apa yang didukung platform. Windows menggunakan UTF-16 secara internal, jadi pada Windows, itu adalah pilihan yang jelas.
Linux sedikit berbeda, tetapi mereka umumnya menggunakan UTF-8 untuk semua yang sesuai dengan Unicode.
Jadi jawaban singkat: Ketiga penyandian dapat menyandikan set karakter yang sama, tetapi mereka mewakili setiap karakter sebagai urutan byte yang berbeda.
Unicode adalah standar dan tentang UTF-x Anda dapat berpikir sebagai implementasi teknis untuk beberapa tujuan praktis:
Saya mencoba memberikan penjelasan sederhana di blogpost saya .
membutuhkan 32 bit (4 byte) untuk mengkodekan karakter apa pun . Misalnya, untuk mewakili titik kode karakter "A" menggunakan skema ini, Anda harus menulis 65 dalam angka biner 32-bit:
00000000 00000000 00000000 01000001 (Big Endian)
Jika Anda melihat lebih dekat, Anda akan melihat bahwa tujuh bit paling kanan sebenarnya adalah bit yang sama ketika menggunakan skema ASCII. Tetapi karena UTF-32 adalah skema lebar tetap , kita harus melampirkan tiga byte tambahan. Berarti bahwa jika kita memiliki dua file yang hanya berisi karakter "A", satu adalah ASCII-encoded dan yang lainnya adalah UTF-32 encoded, ukurannya akan 1 byte dan 4 byte yang sesuai.
Banyak orang berpikir bahwa UTF-32 menggunakan lebar tetap 32 bit untuk mewakili titik kode, UTF-16 adalah lebar tetap 16 bit. SALAH!
Dalam UTF-16 titik kode mungkin direpresentasikan dalam 16 bit, ATAU 32 bit. Jadi skema ini adalah sistem pengkodean panjang variabel. Apa keuntungan dari UTF-32? Setidaknya untuk ASCII, ukuran file tidak akan 4 kali lipat dari aslinya (tapi masih dua kali), jadi kami masih belum kompatibel dengan ASCII.
Karena 7-bit sudah cukup untuk mewakili karakter "A", kita sekarang dapat menggunakan 2 byte bukannya 4 seperti UTF-32. Ini akan terlihat seperti:
00000000 01000001
Anda menebak dengan benar .. Dalam UTF-8 titik kode mungkin direpresentasikan menggunakan 32, 16, 24 atau 8 bit, dan sebagai sistem UTF-16, yang ini juga merupakan sistem pengkodean panjang variabel.
Akhirnya kita dapat merepresentasikan "A" dengan cara yang sama dengan kita merepresentasikannya menggunakan sistem pengkodean ASCII:
01001101
Pertimbangkan huruf Mandarin "語" - penyandian UTF-8 adalah:
11101000 10101010 10011110
Sementara pengkodean UTF-16 lebih pendek:
10001010 10011110
Untuk memahami representasi dan bagaimana interpretasinya, kunjungi posting asli.
UTF-8 akan menjadi yang paling efisien ruang kecuali sebagian besar karakter berasal dari ruang karakter CJK (Cina, Jepang, dan Korea).
UTF-32 adalah yang terbaik untuk akses acak dengan karakter offset ke byte-array.
0xxxxxxx
dalam biner. Semua karakter dua byte dimulai dengan 110xxxxx
byte kedua 10xxxxxx
. Jadi misalkan karakter pertama dari karakter dua byte hilang. Segera setelah Anda melihat 10xxxxxx
tanpa pendahuluan 110xxxxxx
, Anda dapat menentukan dengan pasti bahwa byte hilang atau rusak, dan membuang karakter itu (atau meminta kembali dari server atau apa pun), dan melanjutkan hingga Anda melihat byte pertama yang valid lagi .
Saya membuat beberapa tes untuk membandingkan kinerja database antara UTF-8 dan UTF-16 di MySQL.
Dalam UTF-32 semua karakter dikodekan dengan 32 bit. Keuntungannya adalah Anda dapat dengan mudah menghitung panjang string. Kerugiannya adalah bahwa untuk setiap karakter ASCII Anda membuang tiga byte tambahan.
Dalam karakter UTF-8 memiliki panjang variabel, karakter ASCII dikodekan dalam satu byte (delapan bit), sebagian besar karakter khusus barat dikodekan baik dalam dua byte atau tiga byte (misalnya € adalah tiga byte), dan karakter yang lebih eksotis dapat mengambil hingga empat byte. Kerugian yang jelas adalah, bahwa apriori Anda tidak dapat menghitung panjang string. Tapi itu membutuhkan jauh lebih sedikit byte untuk kode teks alfabet Latin (Inggris), dibandingkan dengan UTF-32.
UTF-16 juga panjang variabel. Karakter dikodekan dalam dua byte atau empat byte. Saya benar-benar tidak mengerti intinya. Ini memiliki kelemahan karena panjang variabel, tetapi belum mendapat keuntungan dari menghemat ruang sebanyak UTF-8.
Dari ketiganya, jelas UTF-8 adalah yang paling banyak tersebar.
Bergantung pada lingkungan pengembangan Anda, Anda bahkan mungkin tidak memiliki pilihan pengkodean tipe data string yang akan digunakan secara internal.
Tetapi untuk menyimpan dan bertukar data saya akan selalu menggunakan UTF-8, jika Anda punya pilihan. Jika Anda memiliki sebagian besar data ASCII, ini akan memberi Anda jumlah data terkecil untuk ditransfer, sambil tetap dapat menyandikan semuanya. Mengoptimalkan untuk I / O terkecil adalah cara untuk menggunakan mesin modern.
Seperti disebutkan, perbedaan utamanya adalah ukuran variabel yang mendasarinya, yang dalam setiap kasus menjadi lebih besar untuk memungkinkan lebih banyak karakter diwakili.
Namun, font, penyandian, dan hal-hal yang rumit rumit (tidak perlu?), Sehingga tautan besar diperlukan untuk mengisi lebih detail:
http://www.cs.tut.fi/~jkorpela/chars.html#ascii
Jangan berharap untuk memahami semuanya, tetapi jika Anda tidak ingin memiliki masalah di kemudian hari, ada baiknya belajar sebanyak yang Anda bisa, sedini mungkin (atau hanya membuat orang lain menyelesaikannya untuk Anda).
Paul.
Singkatnya, satu-satunya alasan untuk menggunakan UTF-16 atau UTF-32 adalah untuk masing-masing mendukung skrip non-Inggris dan kuno.
Saya bertanya-tanya mengapa ada orang yang memilih untuk memiliki pengkodean non-UTF-8 padahal jelas lebih efisien untuk keperluan web / pemrograman.
Kesalahpahaman umum - angka suffix BUKAN indikasi kemampuannya. Mereka semua mendukung Unicode yang lengkap, hanya saja UTF-8 dapat menangani ASCII dengan satu byte, sehingga LEBIH efisien / kurang dapat rusak pada CPU dan melalui internet.
Beberapa bacaan bagus: http://www.personal.psu.edu/ejp10/blogs/gotunicode/2007/10/which_utf_do_i_use.html dan http://utf8everywhere.org