Perbedaan antara UTF-8 dan UTF-16?

140

Perbedaan antara UTF-8 dan UTF-16? Mengapa kita membutuhkan ini?

MessageDigest md = MessageDigest.getInstance("SHA-256");
String text = "This is some text";

md.update(text.getBytes("UTF-8")); // Change this to "UTF-16" if needed
byte[] digest = md.digest();
theJava
sumber
2
jon skeet memiliki artikel bagus tentang pengkodean .... csharpindepth.com/Articles/General/Unicode.aspx
Mitch Wheat

Jawaban:

287

Saya yakin ada banyak artikel bagus tentang ini di seluruh Web, tapi berikut ringkasan singkatnya.

Baik UTF-8 dan UTF-16 adalah pengkodean panjang variabel. Namun, pada UTF-8 sebuah karakter dapat menempati minimal 8 bit, sedangkan pada UTF-16 panjang karakter dimulai dengan 16 bit.

Pro UTF-8 utama:

  • Karakter ASCII dasar seperti angka, karakter Latin tanpa aksen, dll. Menempati satu byte yang identik dengan representasi US-ASCII. Dengan cara ini semua string US-ASCII menjadi UTF-8 yang valid, yang menyediakan kompatibilitas mundur yang layak dalam banyak kasus.
  • Tidak ada byte nol, yang memungkinkan untuk menggunakan string yang diakhiri dengan null, ini juga memperkenalkan banyak kompatibilitas mundur.
  • UTF-8 tidak bergantung pada urutan byte, jadi Anda tidak perlu khawatir tentang masalah Big Endian / Little Endian.

Kontra UTF-8 utama:

  • Banyak karakter umum memiliki panjang yang berbeda, yang memperlambat pengindeksan dengan titik kode dan sangat menghitung jumlah titik kode.
  • Meskipun urutan byte tidak menjadi masalah, terkadang UTF-8 masih memiliki BOM (tanda urutan byte) yang berfungsi untuk memberi tahu bahwa teks dienkode dalam UTF-8, dan juga merusak kompatibilitas dengan perangkat lunak ASCII meskipun teks tersebut hanya berisi karakter ASCII . Perangkat lunak Microsoft (seperti Notepad) sangat suka menambahkan BOM ke UTF-8.

Pro UTF-16 utama:

  • Karakter BMP (bidang multibahasa dasar), termasuk Latin, Sirilik, sebagian besar China (RRT membuat dukungan untuk beberapa titik kode di luar BMP wajib), sebagian besar bahasa Jepang dapat diwakili dengan 2 byte. Ini mempercepat pengindeksan dan menghitung jumlah titik kode jika teks tidak berisi karakter tambahan.
  • Bahkan jika teks memiliki karakter tambahan, mereka masih diwakili oleh pasangan nilai 16-bit, yang berarti bahwa panjang total masih dapat dibagi dua dan memungkinkan untuk menggunakan 16-bit charsebagai komponen primitif dari string.

Kontra UTF-16 utama:

  • Banyak byte nol dalam string US-ASCII, yang berarti tidak ada string yang diakhiri dengan null dan banyak memori yang terbuang.
  • Menggunakannya sebagai pengkodean dengan panjang tetap "sebagian besar berfungsi" dalam banyak skenario umum (terutama di AS / UE / negara-negara dengan abjad Sirilik / Israel / negara Arab / Iran dan banyak lainnya), sering kali menyebabkan dukungan terputus, padahal tidak. Ini berarti programmer harus waspada terhadap pasangan pengganti dan menanganinya dengan benar jika itu penting!
  • Panjangnya bervariasi, jadi titik kode penghitungan atau pengindeksan mahal, meskipun kurang dari UTF-8.

Secara umum, UTF-16 biasanya lebih baik untuk representasi dalam memori karena BE / LE tidak relevan di sana (cukup gunakan urutan asli) dan pengindeksan lebih cepat (jangan lupa untuk menangani pasangan pengganti dengan benar). UTF-8, di sisi lain, sangat bagus untuk file teks dan protokol jaringan karena tidak ada masalah BE / LE dan penghentian null sering kali berguna, serta kompatibilitas ASCII.

Sergei Tachenov
sumber
3
Hanya bagian BE / LE yang hilang pada UTF16 :) UTF-8 memiliki sisi negatif lainnya, ini dapat menghasilkan output yang lebih lama daripada UTF16
bestsss
4
Ya, saya lupa tentang BE / LE. Ini bukan masalah besar, terutama untuk penggunaan dalam memori. UTF-8 akan menghasilkan keluaran yang lebih panjang hanya jika karakter tiga-byte terlibat, tetapi itu berarti kebanyakan bahasa Cina dan Jepang. Di sisi lain, jika teks berisi banyak karakter US-ASCII, itu mungkin menghasilkan keluaran yang lebih pendek, jadi apakah itu sisi negatifnya atau tidak tergantung pada situasi tertentu.
Sergei Tachenov
Saya bahkan tidak berpikir untuk menyebutkan pro langsung dari utf-8, panjangnya lebih pendek. Tentang keluaran yang lebih panjang dari utf-8 itu 'mungkin' karena suatu alasan, namun jika targetnya jauh di timur, pengkodean default harus utf-16. Adapun contoh md.update (text.getBytes ("UTF-8")); pengkodean tidak masalah karena hash stabil di kedua arah.
bestsss
Cara tercepat untuk mengonversi String ke array byte adalah sesuatu seperti itu, diposting sebagai sampel
bestsss
Anda mengatakan karakter memiliki panjang yang berbeda dalam UTF-8 sehingga memperlambat pengindeksan dan menghitung panjang, tetapi saya ragu bahwa karakter dalam UTF-16 memiliki panjang yang berbeda juga, haruskah pengindeksan dan penghitungan panjang UTF-16 lebih cepat?
nicky_zs
19

Mereka hanyalah skema yang berbeda untuk mewakili karakter Unicode.

Keduanya memiliki panjang variabel - UTF-16 menggunakan 2 byte untuk semua karakter dalam bidang multibahasa dasar (BMP) yang berisi sebagian besar karakter yang umum digunakan.

UTF-8 menggunakan antara 1 dan 3 byte untuk karakter di BMP, hingga 4 untuk karakter dalam rentang Unicode saat ini dari U + 0000 hingga U + 1FFFFF, dan dapat diperluas hingga U + 7FFFFFFF jika diperlukan ... tetapi terutama semua karakter ASCII diwakili dalam satu byte masing-masing.

Untuk tujuan intisari pesan, tidak masalah mana dari intisari ini yang Anda pilih, selama semua orang yang mencoba membuat ulang intisari menggunakan opsi yang sama.

Lihat halaman ini untuk mengetahui lebih lanjut tentang UTF-8 dan Unicode.

(Perhatikan bahwa semua karakter Java adalah poin kode UTF-16 di dalam BMP; untuk mewakili karakter di atas U + FFFF, Anda perlu menggunakan pasangan pengganti di Java.)

Jon Skeet
sumber
5

Keamanan: Gunakan hanya UTF-8

Perbedaan antara UTF-8 dan UTF-16? Mengapa kita membutuhkan ini?

Setidaknya ada beberapa kerentanan keamanan dalam implementasi UTF-16 . Lihat Wikipedia untuk detailnya .

WHATWG dan W3C sekarang telah menyatakan bahwa hanya UTF-8 yang akan digunakan di Web.

Masalah [keamanan] yang diuraikan di sini hilang ketika secara eksklusif menggunakan UTF-8, yang merupakan salah satu dari banyak alasan yang sekarang menjadi pengkodean wajib untuk semua hal.

Kelompok lain mengatakan hal yang sama.

Jadi, sementara UTF-16 dapat terus digunakan secara internal oleh beberapa sistem seperti Java dan Windows, sedikit sekali penggunaan UTF-16 yang mungkin pernah Anda lihat di masa lalu untuk file data, pertukaran data, dan semacamnya, kemungkinan besar akan menghilang seluruhnya.

Basil Bourque
sumber
4

Ini tidak terkait dengan UTF-8/16 (secara umum, meskipun memang dikonversi ke UTF16 dan bagian BE / LE dapat disetel dengan satu baris), namun di bawah ini adalah cara tercepat untuk mengubah String menjadi byte []. Misalnya: bagus persis untuk kasus yang disediakan (kode hash). String.getBytes (enc) relatif lambat.

static byte[] toBytes(String s){
        byte[] b=new byte[s.length()*2];
        ByteBuffer.wrap(b).asCharBuffer().put(s);
        return b;
    }
bestsss
sumber
-3

Cara sederhana untuk membedakan UTF-8 dan UTF-16 adalah dengan mengidentifikasi kesamaan di antara keduanya.

Selain berbagi nomor unicode yang sama untuk karakter tertentu, masing-masing memiliki formatnya sendiri.

UTF-8 mencoba untuk menyatakan, setiap nomor unicode diberikan kepada karakter dengan satu byte (Jika itu adalah ASCII), selain itu 2 dua byte, selain itu 4 byte dan seterusnya ...

UTF-16 mencoba untuk menyatakan, setiap nomor unicode diberikan kepada karakter dengan dua byte sebagai permulaan. Jika dua byte tidak cukup, maka gunakan 4 byte. JIKA itu juga tidak cukup, maka gunakan 6 byte.

Secara teoritis, UTF-16 lebih hemat ruang, tetapi dalam praktiknya UTF-8 lebih hemat ruang karena sebagian besar karakter (98% data) untuk diproses adalah ASCII dan UTF-8 mencoba merepresentasikannya dengan byte tunggal dan UTF-16 cobalah untuk merepresentasikannya dengan 2 byte.

Selain itu, UTF-8 adalah superset dari pengkodean ASCII. Jadi setiap aplikasi yang mengharapkan data ASCII juga akan diterima oleh prosesor UTF-8. Ini tidak benar untuk UTF-16. UTF-16 tidak dapat memahami ASCII, dan ini merupakan rintangan besar bagi adopsi UTF-16.

Hal lain yang perlu diperhatikan adalah, semua UNICODE saat ini dapat dimuat dalam maksimum 4 byte UTF-8 (Mengingat semua bahasa di dunia). Ini sama dengan UTF-16 dan tidak ada penghematan nyata dalam ruang dibandingkan dengan UTF-8 ( https://stackoverflow.com/a/8505038/3343801 )

Jadi, orang menggunakan UTF-8 jika memungkinkan.

Venkateswara Rao
sumber