Berapa byte yang diambil oleh satu karakter Unicode?

239

Saya agak bingung tentang penyandian. Sejauh yang saya tahu karakter ASCII lama mengambil satu byte per karakter. Berapa byte yang diperlukan oleh karakter Unicode?

Saya berasumsi bahwa satu karakter Unicode dapat berisi setiap karakter yang mungkin dari bahasa apa pun - apakah saya benar? Jadi berapa byte yang dibutuhkan per karakter?

Dan apa artinya UTF-7, UTF-6, UTF-16 dll. Apakah mereka versi Unicode yang berbeda?

Saya membaca artikel Wikipedia tentang Unicode tetapi cukup sulit bagi saya. Saya menantikan jawaban sederhana.

nan
sumber
15
Maaf, tidak ada jawaban sederhana. Saya menemukan semuanya agak berantakan. Unicode ditagih karena menggunakan dua byte dan dapat mewakili semua karakter, tetapi ternyata dua byte tidak cukup.
Jonathan Wood
12
"Jawaban sederhana": Karakter unicode membutuhkan 1-4 byte. Unicode mencakup banyak bahasa tetapi tidak semua. Terakhir kali saya melihat, misalnya Klingon bukan kumpulan karakter Unicode resmi.
Peter G.
9
Klingon bukan bagian dari standar Unicode itu sendiri, tidak. Ia menggunakan Area Penggunaan Pribadi Uniode (U + F8D0 - U + F8FF) sebagai gantinya.
Remy Lebeau
1
Pertanyaan Juruselamat - terima kasih. Situasi saya menyimpan data melalui SCORM 1.2 LMS yang sesuai ... standar untuk SCORM 1.2 'cmi.suspend_data' adalah 4.096 byte data yang diasumsikan oleh pengembang sebelumnya berarti kami dapat menyimpan 4096 karakter. Oh man dia salah - Saya baru saja menemukan mengapa bookmark kami gagal pada kursus yang panjang. Jadi sekarang saya tahu karena kami menggunakan UTF-8, dibutuhkan 4 byte per karakter memberi kami 1024 karakter.
danjah

Jawaban:

147

Anda tidak akan melihat jawaban sederhana karena tidak ada jawaban.

Pertama, Unicode tidak mengandung "setiap karakter dari setiap bahasa", meskipun itu pasti mencoba.

Unicode itu sendiri adalah pemetaan, mendefinisikan codepoints dan codepoint adalah angka, biasanya dikaitkan dengan karakter. Saya katakan biasanya karena ada konsep seperti menggabungkan karakter. Anda mungkin terbiasa dengan hal-hal seperti aksen, atau umlaut. Itu dapat digunakan dengan karakter lain, seperti a aatau a uuntuk membuat karakter logis baru. Karenanya karakter dapat terdiri dari 1 atau lebih codepoint.

Agar bermanfaat dalam sistem komputasi, kita perlu memilih representasi untuk informasi ini. Itu adalah berbagai pengkodean unicode, seperti utf-8, utf-16le, utf-32 dll. Mereka dibedakan sebagian besar oleh ukuran unit kode mereka. UTF-32 adalah pengkodean yang paling sederhana, ia memiliki kode unit yaitu 32 bit, yang berarti suatu titik kode individu cocok dengan nyaman ke dalam kode unit. Pengkodean lainnya akan memiliki situasi di mana codepoint akan membutuhkan beberapa kode unit, atau bahwa codepoint tertentu tidak dapat diwakili dalam pengkodean sama sekali (ini adalah masalah misalnya dengan UCS-2).

Karena fleksibilitas menggabungkan karakter, bahkan dalam pengkodean yang diberikan jumlah byte per karakter dapat bervariasi tergantung pada karakter dan bentuk normalisasi. Ini adalah protokol untuk berurusan dengan karakter yang memiliki lebih dari satu representasi (Anda dapat mengatakan "an 'a' with an accent"yang merupakan 2 codepoint, salah satunya adalah char yang menggabungkan atau "accented 'a'"yang merupakan satu codepoint).

Logan Capaldo
sumber
1
BAIK. Lalu berapa byte yang mengambil satu karakter yang diwakili dalam satu codepoint yang diberikan? Misalnya ruang yang tidak putus-putus.
Nicolas Barbulesco
Menggabungkan karakter membuat hidup seorang programmer seperti ketika menulis strlen (), substr () dan fungsi manipulasi string lainnya pada array UTF8. Pekerjaan seperti ini tidak akan pernah lengkap dan selalu bermasalah.
Nulik
Saya menulis demo yang menunjukkan file yang disandikan Windows-1252, UTF8 dan UTF8-BOM diinterpretasikan dengan setiap penyandian, dan membandingkan kesetaraan antara hasil: github.com/vladyrn/encodings_demo
Vlad
195

Anehnya, tidak ada yang menunjukkan bagaimana cara menghitung berapa byte yang mengambil satu karakter Unicode. Berikut adalah aturan untuk string yang dikodekan UTF-8:

Binary    Hex          Comments
0xxxxxxx  0x00..0x7F   Only byte of a 1-byte character encoding
10xxxxxx  0x80..0xBF   Continuation byte: one of 1-3 bytes following the first
110xxxxx  0xC0..0xDF   First byte of a 2-byte character encoding
1110xxxx  0xE0..0xEF   First byte of a 3-byte character encoding
11110xxx  0xF0..0xF7   First byte of a 4-byte character encoding

Jadi jawaban cepatnya adalah: dibutuhkan 1 hingga 4 byte, tergantung pada yang pertama yang akan menunjukkan berapa banyak byte yang dibutuhkan.

paul.ago
sumber
8
Saya percaya nilai Hex maksimum untuk karakter 4-byte adalah 0xF7 (bukan 0xF4).
DJPJ
Terima kasih banyak! Saya hanya mengontrol + melalui standar IETF, dan saya tidak menemukan apa pun tentang penyandian, dan artikel yang saya baca tidak masuk ke detail yang cukup untuk mengatakan berapa banyak bit yang digunakan untuk mewakili jumlah kode trailing poin per "karakter".
MarcusJ
1
Ini sekarang di halaman kedua dari lembar contekan "pengantar untuk anggota tim baru" saya, bersama dengan dua komentar pertama yang lucu
Cee McSharpface
1
0xF4 bukan kesalahan tetapi klarifikasi. Codepoint Unicode berada dalam kisaran 0-0x10ffff sehingga codepoint terakhir dikodekan sebagai F4 8F BF BF.
Frediano Ziglio
38

Saya tahu pertanyaan ini sudah lama dan sudah memiliki jawaban yang diterima, tetapi saya ingin menawarkan beberapa contoh (berharap itu akan bermanfaat bagi seseorang).

Sejauh yang saya tahu karakter ASCII lama mengambil satu byte per karakter.

Baik. Sebenarnya, karena ASCII adalah enkode 7-bit, ia mendukung 128 kode (95 di antaranya dapat dicetak), sehingga hanya menggunakan setengah byte (jika itu masuk akal).

Berapa byte yang diperlukan oleh karakter Unicode?

Unicode hanya memetakan karakter ke codepoint. Itu tidak menentukan cara menyandikannya. File teks tidak mengandung karakter Unicode, tetapi byte / oktet yang mungkin mewakili karakter Unicode.

Saya berasumsi bahwa satu karakter Unicode dapat berisi setiap karakter yang mungkin dari bahasa apa pun - apakah saya benar?

Tidak. Tapi hampir. Jadi pada dasarnya ya. Tapi tetap tidak.

Jadi berapa byte yang dibutuhkan per karakter?

Sama seperti pertanyaan kedua Anda.

Dan apa arti UTF-7, UTF-6, UTF-16 dll? Apakah mereka semacam versi Unicode?

Tidak, itu adalah pengkodean. Mereka menentukan bagaimana byte / oktet harus mewakili karakter Unicode.

Beberapa contoh. Jika beberapa di antaranya tidak dapat ditampilkan di browser Anda (mungkin karena font tidak mendukungnya), buka http://codepoints.net/U+1F6AA(ganti 1F6AAdengan codepoint in hex) untuk melihat gambar.

    • U + 0061 SURAT KECIL LATIN A: a
      • Nº: 97
      • UTF-8: 61
      • UTF-16: 00 61
    • TANDA HAK CIPTA U + 00A9: ©
      • Nº: 169
      • UTF-8: C2 A9
      • UTF-16: 00 A9
    • TANDA REGISTERED U + 00AE: ®
      • Nº: 174
      • UTF-8: C2 AE
      • UTF-16: 00 AE
    • U + 1337 PHWA SYLLABLE ETHIOPIC:
      • Nº: 4919
      • UTF-8: E1 8C B7
      • UTF-16: 13 37
    • U + 2014 EM DASH:
      • Nº: 8212
      • UTF-8: E2 80 94
      • UTF-16: 20 14
    • U + 2030 TANDA PER Mille:
      • Nº: 8240
      • UTF-8: E2 80 B0
      • UTF-16: 20 30
    • TANDA U + 20AC EURO:
      • Nº: 8364
      • UTF-8: E2 82 AC
      • UTF-16: 20 AC
    • TANDA TANDA PERDAGANGAN U + 2122:
      • Nº: 8482
      • UTF-8: E2 84 A2
      • UTF-16: 21 22
    • U + 2603 SNOWMAN:
      • Nº: 9731
      • UTF-8: E2 98 83
      • UTF-16: 26 03
    • U + 260E TELEPON HITAM:
      • Nº: 9742
      • UTF-8: E2 98 8E
      • UTF-16: 26 0E
    • U + 2614 PAYUNG DENGAN DROPS HUJAN:
      • Nº: 9748
      • UTF-8: E2 98 94
      • UTF-16: 26 14
    • U + 263A WAJAH SMILING PUTIH:
      • Nº: 9786
      • UTF-8: E2 98 BA
      • UTF-16: 26 3A
    • U + 2691 BENDERA HITAM:
      • Nº: 9873
      • UTF-8: E2 9A 91
      • UTF-16: 26 91
    • SIMBOL ATOM U + 269B:
      • Nº: 9883
      • UTF-8: E2 9A 9B
      • UTF-16: 26 9B
    • U + 2708 PESAWAT:
      • Nº: 9992
      • UTF-8: E2 9C 88
      • UTF-16: 27 08
    • U + 271E SALING LATIN PUTIH:
      • Nº: 10014
      • UTF-8: E2 9C 9E
      • UTF-16: 27 1E
    • U + 3020 FACE MARK POSTAL:
      • Nº: 12320
      • UTF-8: E3 80 A0
      • UTF-16: 30 20
    • U + 8089 CJK UNIFIED IDEOGRAPH-8089:
      • Nº: 32905
      • UTF-8: E8 82 89
      • UTF-16: 80 89
    • U + 1F4A9 PILE OF POO: 💩
      • Nº: 128169
      • UTF-8: F0 9F 92 A9
      • UTF-16: D8 3D DC A9
    • ROKET U + 1F680: 🚀
      • Nº: 128640
      • UTF-8: F0 9F 9A 80
      • UTF-16: D8 3D DE 80

Oke saya terbawa ...

Fakta menyenangkan:

basic6
sumber
Unit kode dalam UTF-16 memiliki lebar 16 bit. Anda menunjukkan mereka dengan ruang di tengah, yang menyesatkan. Representasi UTF-16 untuk © lebih baik 00A9daripada 00 A9(yang akan menjadi UTF-16BE).
Roland Illig
Apa bedanya? Tidak MENJADI endian besar? Dia menulisnya dalam big endian, jadi file yang ditulis dalam big endian UTF-16 akan sama dengan UTF-16BE, kan?
HappyPandaFace
6
Koreksi: 1) ASCII adalah 7 bit, satu byte adalah 8 bit, jadi lebih dari setengahnya. 2) Unicode tidak mendefinisikan cara mengkodekan poin kode. UTF-8, UTF-16 dan UTF-32 didefinisikan dalam Standar Unicode.
Jonathan Rosenne
3
@ JonathanRosenne Saya pikir s / dia maksudnya hanya menggunakan setengah dari nilai yang mungkin diwakili dengan 8 bit, bukan menggunakan setengah dari bit.
Aritz Lopez
2
Saya sangat suka contohnya. Mereka menyoroti mengapa orang lebih suka UTF-16 daripada UTF-8, misalnya. Pengembang perangkat lunak yang berbeda dapat memilih pengkodean yang berbeda berdasarkan karakter Unicode yang lebih mungkin digunakan. Di Cina / Jepang misalnya, UTF-16 (2-byte) lebih masuk akal daripada UTF-8 untuk mereka, karena karakter yang sama sering membutuhkan byte dua kali lebih banyak untuk dikodekan dalam UTF-8
mike
29

Sederhananya Unicodeadalah standar yang menetapkan satu nomor (disebut titik kode) untuk semua karakter di dunia (Masih bekerja dalam proses).

Sekarang Anda harus mewakili poin kode ini menggunakan byte, itu disebut character encoding. UTF-8, UTF-16, UTF-6adalah cara untuk mewakili karakter tersebut.

UTF-8adalah pengkodean karakter multibyte. Karakter dapat memiliki 1 hingga 6 byte (beberapa di antaranya mungkin tidak diperlukan saat ini).

UTF-32 setiap karakter memiliki 4 byte a karakter.

UTF-16menggunakan 16 bit untuk setiap karakter dan itu hanya mewakili sebagian dari karakter Unicode yang disebut BMP (untuk semua keperluan praktis itu cukup). Java menggunakan pengkodean ini dalam string-nya.

Zimbabao
sumber
10
Unicode adalah seperangkat kode 21-bit dan 4 byte cukup untuk mewakili karakter Unicode dalam UTF-8. UTF-16 menggunakan pengganti untuk mewakili karakter di luar BMP (pesawat multibahasa dasar); diperlukan 2 atau 4 byte untuk mewakili karakter Unicode yang valid. UCS-2 adalah varian hanya 16-bit dari UTF-16 tanpa dukungan untuk pengganti atau karakter di luar BMP.
Jonathan Leffler
1
Anda benar. UTF-8 yang asli memiliki 6 byte untuk menampung 32 bit. Saya sebenarnya tidak ingin terlalu menyulitkan karena dia sudah bingung dengan wiki doc :)
Zimbabao
3
Jawaban ini menyatakan bahwa UTF-16 tidak dapat menyandikan poin kode BMP. Ini tidak benar, karena ini dapat dikodekan seperti yang mereka bisa di UTF-8 menggunakan pasangan pengganti. (Anda harus memikirkan UCS-2 yang ketinggalan jaman, sebelum Unicode 2.0 keluar, yang hanya menyandikan titik kode 16-bit.) Juga, Java tidak cukup menggunakan UTF-16, ia menggunakan bentuk yang telah dimodifikasi di mana titik kode 0 dikodekan secara berbeda.
rdb
@rdb - Ini adalah kebalikannya. Jawabannya mengatakan bahwa UTF-16 mewakili BMP.
Nicolas Barbulesco
3
Saya salah ketik; Saya bermaksud mengatakan "non-BMP". Kesalahan dalam jawabannya adalah bahwa ia mengatakan bahwa UTF-16 mewakili karakter BMP, yang tidak akurat. UTF-16 dapat menyandikan semua karakter unicode - karakter non-BMP dikodekan melalui pasangan pengganti. Mungkin penjawabnya bingung dengan UCS-2.
rdb
17

Di UTF-8:

1 byte:       0 -     7F     (ASCII)
2 bytes:     80 -    7FF     (all European plus some Middle Eastern)
3 bytes:    800 -   FFFF     (multilingual plane incl. the top 1792 and private-use)
4 bytes:  10000 - 10FFFF

Dalam UTF-16:

2 bytes:      0 -   D7FF     (multilingual plane except the top 1792 and private-use )
4 bytes:   D800 - 10FFFF

Di UTF-32:

4 bytes:      0 - 10FFFF

10FFFF adalah codepoint unicode terakhir menurut definisi, dan didefinisikan demikian karena itu adalah batas teknis UTF-16.

Ini juga merupakan codepoint terbesar UTF-8 yang dapat mengkodekan dalam 4 byte, tetapi ide di balik pengkodean UTF-8 juga bekerja untuk pengkodean 5 dan 6 byte untuk mencakup codepoint sampai 7FFFFFFF, yaitu. setengah dari apa yang bisa UTF-32.

John
sumber
8

Di Unicode jawabannya tidak mudah diberikan. Masalahnya, seperti yang sudah Anda tunjukkan, adalah pengkodeannya.

Diberikan kalimat bahasa Inggris apa pun tanpa karakter diakritik, jawaban untuk UTF-8 akan sebanyak byte sebagai karakter dan untuk UTF-16 adalah jumlah karakter dikali dua.

Satu-satunya penyandian di mana (sampai sekarang) kita dapat membuat pernyataan tentang ukurannya adalah UTF-32. Selalu ada 32bit per karakter, meskipun saya membayangkan bahwa poin kode disiapkan untuk UTF-64 masa depan :)

Yang menyulitkan adalah setidaknya dua hal:

  1. karakter tersusun, di mana alih-alih menggunakan entitas karakter yang sudah beraksen / diakritik (À), pengguna memutuskan untuk menggabungkan aksen dan karakter dasar (`A).
  2. poin kode. Poin kode adalah metode dimana penyandian-UTF memungkinkan untuk menyandikan lebih dari jumlah bit yang memberi mereka nama mereka biasanya mengizinkan. Misalnya UTF-8 menunjuk byte tertentu yang dengan sendirinya tidak valid, tetapi ketika diikuti oleh byte kelanjutan yang valid akan memungkinkan untuk menggambarkan karakter di luar kisaran 8-bit dari 0..255. Lihat Contoh dan Pengkodean Berlebih di bawah ini dalam artikel Wikipedia di UTF-8.
    • Contoh yang sangat baik mengingat ada adalah bahwa € karakter (titik kode U+20ACdapat direpresentasikan baik sebagai tiga byte urutan E2 82 ACatau empat byte urutan F0 82 82 AC.
    • Keduanya valid, dan ini menunjukkan betapa rumitnya jawabannya ketika berbicara tentang "Unicode" dan bukan tentang pengkodean khusus Unicode, seperti UTF-8 atau UTF-16.
0xC0000022L
sumber
4

Yah saya baru saja menarik halaman Wikipedia juga, dan di bagian intro saya melihat "Unicode dapat diimplementasikan dengan pengkodean karakter yang berbeda. Pengkodean yang paling umum digunakan adalah UTF-8 (yang menggunakan satu byte untuk setiap karakter ASCII, yang memiliki nilai kode yang sama dalam pengkodean UTF-8 dan ASCII, dan hingga empat byte untuk karakter lain), UCS-2 yang sekarang usang (yang menggunakan dua byte untuk setiap karakter tetapi tidak dapat menyandikan setiap karakter dalam standar Unicode saat ini) "

Seperti yang ditunjukkan oleh kutipan ini, masalah Anda adalah Anda mengasumsikan Unicode adalah satu-satunya cara penyandian karakter. Sebenarnya ada beberapa bentuk Unicode, dan, sekali lagi dalam kutipan itu, salah satunya bahkan memiliki 1 byte per karakter seperti apa yang Anda gunakan.

Jadi jawaban sederhana yang Anda inginkan adalah bervariasi.

Loduwijk
sumber
3

Untuk UTF-16, karakter membutuhkan empat byte (dua unit kode) jika dimulai dengan 0xD800 atau lebih besar; karakter seperti itu disebut "pasangan pengganti." Lebih khusus, pasangan pengganti memiliki bentuk:

[0xD800 - 0xDBFF]  [0xDC00 - 0xDFF]

di mana [...] menunjukkan unit kode dua byte dengan rentang yang diberikan. Apa pun <= 0xD7FF adalah satu unit kode (dua byte). Apa pun> = 0xE000 tidak valid (kecuali penanda BOM, bisa dibilang).

Lihat http://unicodebook.readthedocs.io/unicode_encodings.html , bagian 7.5.

Prewett
sumber
1

Dari Wiki:

UTF-8, pengodean lebar variabel 8-bit yang memaksimalkan kompatibilitas dengan ASCII;

UTF-16, 16-bit, pengodean lebar variabel;

UTF-32, pengodean lebar tetap 32-bit.

Ini adalah tiga pengkodean berbeda yang paling populer.

  • Dalam UTF-8 setiap karakter dikodekan ke dalam 1 hingga 4 byte (pengodean dominan)
  • Dalam UTF16 setiap karakter dikodekan menjadi 1 hingga dua kata 16-bit dan
  • di UTF-32 setiap karakter dikodekan sebagai kata 32-bit tunggal.
chikitin
sumber
1

Unicodeadalah standar yang menyediakan angka unik untuk setiap karakter. Angka-angka unik ini disebut code points (yang hanya kode unik) untuk semua karakter yang ada di dunia (beberapa masih akan ditambahkan).

Untuk tujuan yang berbeda, Anda mungkin perlu merepresentasikan ini code pointsdalam byte (kebanyakan bahasa pemrograman melakukannya), dan di sinilah Character Encodingtendangan masuk.

UTF-8, UTF-16, UTF-32Dan sebagainya semua Character Encodings, dan poin kode Unicode terwakili dalam pengkodean ini, dengan cara yang berbeda.


UTF-8 pengkodean memiliki panjang lebar variabel, dan karakter, yang dikodekan di dalamnya, dapat menempati 1 hingga 4 byte inklusif;

UTF-16memiliki panjang variabel dan karakter, yang dikodekan di dalamnya, dapat mengambil 1 atau 2 byte (yaitu 8 atau 16 bit). Ini hanya mewakili sebagian dari semua karakter Unicode yang disebut BMP (Basic Multilingual Plane) dan itu sudah cukup untuk hampir semua kasus. Java menggunakan UTF-16pengodean untuk string dan karakternya;

UTF-32 memiliki panjang tetap dan masing-masing karakter membutuhkan tepat 4 byte (32 bit).

Giorgi Tsiklauri
sumber