UTF-8 kaç karakter kodlayabilir?


100

UTF-8'in 8 bit olması, en fazla 256 farklı karakter olabileceği anlamına gelmez mi?

İlk 128 kod noktası ASCII'deki ile aynıdır. Ancak UTF-8'in milyon karaktere kadar destekleyebileceğini söylüyor?

Bu nasıl çalışıyor?


2
Lütfen bu soruyu yeniden değerlendirin çünkü tüm cevaplar yanlış. Cevabımı oku: stackoverflow.com/a/45042566/124486
Evan Carroll

Unicode'un UTF-8, UTF-16, UTF-32 kodlamalarında sayı, kod birimlerindeki bit sayısıdır ve bunlardan biri veya daha fazlası bir Unicode kod noktasını kodlar.
Tom Blodget

1
Bu soruyu bir süre önce düzeltmek için cevap verdim: Seçilen cevaba karşı tartarsanız harika olurdu, bu tam anlamıyla tüm hikayeyi anlatmayan tek bir wikipedia alıntıdır (umarım güncellemem çok daha net)
Evan Carroll

Yanıtlar:


137

UTF-8 her zaman bir bayt kullanmaz, 1 ila 4 bayttır.

İlk 128 karakter (US-ASCII) bir bayta ihtiyaç duyar.

Sonraki 1.920 karakterin kodlanması için iki bayta ihtiyaç vardır. Bu, hemen hemen tüm Latin alfabelerinin geri kalanını ve ayrıca Yunan, Kiril, Kıpti, Ermenice, İbranice, Arapça, Süryanice ve Tāna alfabelerini ve Aksan İşaretlerini Birleştirme'yi kapsar.

Çoğu Çince, Japonca ve Korece [CJK] karakterleri de dahil olmak üzere ortak kullanımdaki [12] hemen hemen tüm karakterleri içeren Temel Çok Dilli Düzlemin geri kalanındaki karakterler için üç bayta ihtiyaç vardır.

Daha az yaygın CJK karakterleri, çeşitli tarihi komut dosyaları, matematiksel semboller ve emoji (piktografik semboller) içeren diğer Unicode düzlemlerindeki karakterler için dört bayta ihtiyaç vardır.

kaynak: Wikipedia


merhaba @zwippie bunda yeniyim. Anlamadığım bir şey var.! BMP, 3 olduğunu söylediğiniz 2 bayt kullanır? Yanlış mıyım?
chiperortiz

1
@chiperortiz, BMP aslında 16 bittir, bu nedenle karakter başına sabit uzunlukta UTF-16 olarak kodlanabilir (UTF-16 ayrıca 16 bitin ötesine geçmeyi destekler, ancak bu zor bir uygulamadır ve birçok uygulama bunu desteklemez). Bununla birlikte, UTF-8 için, ne kadar süreceğini de kodlamanız gerekir, böylece bazı bitleri kaybedersiniz. Bu nedenle BMP'nin tamamını kodlamak için 3 bayta ihtiyacınız var. Bu savurgan görünebilir, ancak UTF-16'nın her zaman 2 bayt kullandığını, ancak UTF-8'in çoğu latin tabanlı dil karakteri için karakter başına bir bayt kullandığını unutmayın. İki kat daha kompakt hale getiriyor.
sanderd17

OP'nin sorusunun ana dürtüsü, neden UTF- 8 olarak adlandırıldığıyla ilgilidir - bu, buna gerçekten cevap vermez.
jbyrd

43

UTF-8 karakter başına 1-4 bayt kullanır: ascii karakterleri için bir bayt (ilk 128 unicode değeri ascii ile aynıdır). Ancak bu yalnızca 7 bit gerektirir. En yüksek ("işaret") bit ayarlanmışsa, bu çok baytlı bir dizinin başlangıcını gösterir; ardışık yüksek bit kümesinin sayısı, bayt sayısını, ardından bir 0'ı gösterir ve kalan bitler değere katkıda bulunur. Diğer baytlar için, en yüksek iki bit 1 ve 0 olacaktır ve kalan 6 bit değer içindir.

Dolayısıyla, dört baytlık bir dizi 11110 ... ile başlayacaktır (ve ... = değer için üç bit), ardından değer için her biri 6 bit olan üç bayt 21 bitlik bir değer verecektir. 2 ^ 21, unicode karakterlerinin sayısını aştığından, tüm unicode UTF8 olarak ifade edilebilir.


@NickL. Hayır, 3 bayt demek istiyorum. Bir çokbaytlı ilk baytı 1111 başlarsa bu örnekte, 1 ilk olarak gösterir olan bir baytlı dizisinin başlangıcı, ondan sonra art arda 1 'lerin sayısı sayısını gösterir ek birinci bir çok sırayla bayt ( bayt 110, 1110 veya 11110'dan başlayacaktır).
CodeClown42

RFC 3629. tools.ietf.org/html/rfc3629#section-3'te sözcükleriniz için kanıt bulundu . Ancak, ikinci bayt 110xxxxx 10xxxxxx'in başına neden "10" koymam gerektiğini anlamıyorum? Neden sadece 110xxxxx xxxxxxxx değil?
kolobok

3
Softwareengineering.stackexchange.com/questions/262227/… 'de yanıt bulundu . Sadece güvenlik nedenleriyle (akışın ortasındaki tek bir baytın bozulması durumunda)
kolobok

@kolobok Ah. Sans güvenliği daha sonra 21 bitlik bir değeri 3 bayt olarak kodlayabilirsiniz (uzunluğu belirten 3 bit artı 21 bit). : D Muhtemelen bu o kadar anlamlı değil, en azından WRT Batı dilleri.
CodeClown42

Sanırım NickL bunu sordu ama eğer ... bitler yerine sonraki baytları temsil ediyorsa, o ilk bayttaki diğer bitlere ne oldu?
c6754

27

Göre bu tablodaki * UTF-8 gerektiğini desteklemektedir:

2 31 = 2.147.483.648 karakter

Ancak, RFC 3629 olası değerleri kısıtladı, bu nedenle şimdi 4 bayt ile sınırlandık , bu da bize

2 21 = 2.097.152 karakter

Bu karakterlerin büyük bir kısmının özel kullanım için "ayrılmış" olduğuna dikkat edin, bu aslında simge yazı tipleri için oldukça kullanışlıdır.

* Kullanılan Wikipedia 6 baytlık bir tablo gösteriyor - o zamandan beri makaleyi güncellediler.

2017-07-11: Birden çok bayt ile kodlanmış aynı kod noktasının iki kez sayılması nedeniyle düzeltildi


Bu cevap, olası kodlama sayısını iki kez saymaktır. Tüm 2 ^ 7'yi saydıktan sonra, bunları 2 ^ 11, 2 ^ 16, vb. İçinde tekrar sayamazsınız. Mümkün olan doğru kodlama sayısı 2 ^ 21'dir (ancak hepsi şu anda kullanılmamaktadır).
Jimmy

@Jimmy Çift saydığıma emin misin? 0xxxxxxx7 kullanılabilir bit 110xxxxx 10xxxxxxverir, 11 tane daha verir - örtüşme olmaz. İlk bayt 0, ilk durumda ve 1ikinci durumda ile başlar.
mpen

@mpen yani hangi kod noktası 00000001depolanır ve neyi 11000000 100000001depolar?
Evan Carroll

1
@EvanCarroll Uhh .... puan alındı. Aynı kod noktasını kodlamanın birden fazla yolu olduğunu fark etmemiştim.
mpen

1
Bunu kendim cevaplamaya çalıştım, bunun daha iyi bir açıklama ve soruya cevap olduğunu düşünüyor musunuz bir bakın: stackoverflow.com/a/45042566/124486
Evan Carroll

22

Unicode ve UTF-8

Unicode, kod noktalarını karakterlere çözümler. UTF-8, Unicode için bir depolama mekanizmasıdır. Unicode'un bir özelliği vardır. UTF-8'in bir özelliği vardır. İkisinin de farklı sınırları vardır. UTF-8'in farklı bir yukarı sınırı vardır.

Unicode

Unicode, "uçaklar" ile belirtilir . Her uçak 2 16 kod noktası taşır . Unicode'da 17 Uçak var. Toplam 17 * 2^16kod noktası için. İlk uçak, uçak 0 veya BMP , taşıdığı şeyin ağırlığında özeldir.

Tüm nüansları açıklamak yerine, yukarıdaki uçaklarla ilgili makaleyi aktarmama izin verin.

17 uçak, 1.114.112 kod noktası barındırabilir. Bunların 2.048'i vekillerdir, 66'sı karakter değildir ve 137.468'i özel kullanım için ayrılmış olup, 974.530'u genel atama için bırakmıştır.

UTF-8

Şimdi yukarıda bağlantısı verilen makaleye geri dönelim,

UTF-8 tarafından kullanılan kodlama şeması, 2 31 kod noktası (32.768 düzlem) gibi çok daha büyük bir sınırla tasarlanmıştır ve 4 bayt ile sınırlı olsa bile 2 21 kod noktasını (32 düzlem) kodlayabilir . [3] Unicode, kod noktalarını UTF-16 tarafından kodlanabilen 17 düzlemle sınırladığından, 0x10FFFF üzerindeki kod noktaları UTF-8 ve UTF-32'de geçersizdir.

Böylece, geçerli Unicode olmayan şeyleri UTF-8'e koyabileceğinizi görebilirsiniz. Neden? UTF-8, Unicode'un desteklemediği kod noktalarını barındırdığı için.

UTF-8, dört baytlık bir sınırlamayla bile, 2 21 kod noktasını destekler ki bu,17 * 2^16


20

2.164.864 "karakter" potansiyel olarak UTF-8 tarafından kodlanabilir.

Bu sayı, kodlamanın çalışma şeklinden gelir:27 + 211 + 216 + 221

  • 1 baytlık karakterlerin kodlama için 7 biti vardır 0xxxxxxx(0x00-0x7F)

  • 2 baytlık karakterlerde kodlama için 11 bit bulunur 110xxxxx 10xxxxxx(ilk bayt için 0xC0-0xDF; ikincisi için 0x80-0xBF)

  • 3 baytlık karakterlerin kodlama için 16 bitleri vardır 1110xxxx 10xxxxxx 10xxxxxx(ilk bayt için 0xE0-0xEF; devam baytları için 0x80-0xBF)

  • 4 baytlık karakterlerin kodlama için 21 biti vardır 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx(ilk bayt için 0xF0-0xF7; devam baytları için 0x80-0xBF)

Gördüğünüz gibi bu, mevcut Unicode'dan (1.112.064 karakter) önemli ölçüde daha büyük.

GÜNCELLEME

İlk hesaplamam yanlış çünkü ek kuralları dikkate almıyor. Daha fazla ayrıntı için bu cevaba yapılan yorumlara bakın.


2
Matematiğiniz, yalnızca en kısa kod birimi dizisinin bir kod noktasını kodlamasına izin verilen UTF-8 kuralına uymuyor. Dolayısıyla, 00000001, U + 0001 için geçerlidir, ancak 11110000 10000000 10000000 10000001 geçerli değildir. Ref: Tablo 3-7. İyi Biçimlendirilmiş UTF-8 Bayt Dizileri . Ayrıca, soru doğrudan tablo tarafından yanıtlanır: sadece aralıkları toplarsınız. (UTF-16'nın yerine geçenleri dışlamak için ayrıktırlar).
Tom Blodget

Tom - yorumunuz için teşekkürler! Bu kısıtlamaların farkında değildim. Tablo 3-7'yi gördüm ve sayıları araştırdım ve görünüşe göre 1.083.392 olası geçerli sıra var.
Ruben Reyes

Bu doğru bir cevap. Diğer cevaplar az önce durdu 2^21ve diğer olası kombinasyonları unuttu.
Manu Manjunath

6

UTF-8, karakter başına minimum 8 bit içeren değişken uzunluklu bir kodlamadır . Daha yüksek kod puanına sahip karakterler 32 bit alacaktır.


2
Bu yanıltıcıdır. Sahip olabileceğiniz en uzun kod noktası 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx, gerçek karakteri kodlamak için yalnızca 21 bit kullanılabilir.
Boris

6
Kod noktalarının kodlanmasının 32 bit kadar sürebileceğini söyledim, hiçbir zaman (tümevarım yoluyla) 32 bit UTF-8'de 2 ^ 32 karakteri kodlayabileceğinizi iddia etmedim. Eğer kodlamak beri Ama bu, oldukça tartışma götürür tüm UTF-8, mevcut Unicode karakterleri ve yapabilirsiniz hatta daha sen (mevcut ancak kaldırılmış olan) UTF-8-48 bit germek eğer kodlamak Emin Ne değilim bu yüzden, yanıltıcı nokta.
kestirmek


2

Unicode Standardına ve SSS girişi, UTF-8 UTF-16, UTF-32 ve BOM gibi ilgili bilgilere göz atın . Bu o kadar düzgün bir seyir değil, ancak güvenilir bir bilgi ve başka yerlerde UTF-8 hakkında okuyabileceğiniz şeylerin çoğu şüpheli.

“UTF-8” deki “8” kod birimlerinin bit cinsinden uzunluğuyla ilgilidir . Kod birimleri, karakterleri kodlamak için kullanılan varlıklardır, basit bir bire bir eşleme olması gerekmez. UTF-8, bir karakteri kodlamak için değişken sayıda kod birimi kullanır.

UTF-8'de kodlanabilen karakter koleksiyonu, UTF-16 veya UTF-32 ile tamamen aynıdır, yani tüm Unicode karakterleri. Hepsi, karakter olmayanları ve atanmamış kod noktalarını da içeren tüm Unicode kodlama alanını kodlar.


1

Mevcut maksimum UTF-8 kodları (2.164.864) konusunda mpen ile hemfikir olsam da (aşağıda listelenmiştir, onun hakkında yorum yapamam), UTF-8'in 2 ana kısıtlamasını kaldırırsanız 2 seviye geride kalır: sadece 4 bayt limit ve 254 ve 255 kodları kullanılamaz (sadece 4 bayt limitini kaldırdı).

Başlangıç ​​kodu 254, başlangıç ​​bitlerinin temel düzenlemesini izler (çok bitli bayrak 1'e ayarlanmış, 6 1'lik bir sayım ve terminal 0, yedek bit yok) birlikte çalışmanız için 6 ek bayt verir (6 10xxxxxx grup, ek 2 ^ 36 kod).

Başlangıç ​​kodu 255 temel kurulumu tam olarak takip etmez, terminal 0 yoktur, ancak tüm bitler size 7 ek bayt verir (çok bitli bayrak 1'e ayarlanmış, 7 1'in sayısı ve tüm bitler kullanıldığı için terminal 0 yok) ; 7 10xxxxxx grubu, ek 2 ^ 42 kod).

Bunları eklemek, 4,468,982,745,216 nihai maksimum gösterilebilir karakter kümesi verir. Bu, mevcut kullanımdaki, eski veya ölü dillerdeki ve kaybolduğuna inanılan dillerdeki tüm karakterlerden daha fazlasıdır. Melek veya Göksel senaryo var mı?

Ayrıca, 254 ve 255: 128-191 ve birkaçına ek olarak UTF-8 standardında gözden kaçan / yok sayılan tek bayt kodları vardır. Bazıları klavye tarafından yerel olarak kullanılır, örnek kod 128 genellikle bir silme geri almasıdır. Diğer başlangıç ​​kodları (ve ilişkili aralıklar) bir veya daha fazla nedenden dolayı geçersizdir ( https://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences ).


0

Unicode, UTF-8 ile sıkı bir şekilde evlidir. Unicode, UTF-8 tarafından desteklenen tam olarak aynı sayıda kod noktası olan 2 ^ 21 kod noktasını (2.097.152 karakter) özellikle destekler. Her iki sistem de kod noktaları vb. İçin aynı 'ölü' alanı ve sınırlı bölgeleri ayırır ... Haziran 2018 itibarıyla en son sürüm olan Unicode 11.0 137.439 karakterlik bir repertuar içerir

Unicode standardından. Unicode SSS

Unicode Standard, 21 bitlik bir kod alanı anlamına gelen U + 0000..U + 10FFFF aralığındaki karakterleri kodlar.

UTF-8 Wikipedia sayfasından. UTF-8 Tanımı

Unicode kod uzayının 2003 yılında 21 bitlik değerlerle kısıtlanmasından bu yana, UTF-8 kod noktalarını bir ila dört bayta kodlamak için tanımlanmıştır, ...


21 bit yukarı yuvarlanır. Unicode, söylediği gibi 1.114.112 kod noktasını (U + 0000 - U + 10FFFF) destekler. (Bazen 65536'nın 17 uçağı olarak tanımlanır.)
Tom Blodget

@TomBlodget, haklısınız. Bu tartışmadan en alakalı çıkarım, UTF-8'in Unicode standardında halihazırda tanımlanmış tüm noktaları kodlayabilmesi ve büyük olasılıkla bunu uzun bir süre daha yapabilmesidir.
Görünen ad
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.