UTF-8 "değişken genişlikli kodlama" nasıl çalışır?


110

Unicode standardı, hepsini depolamak için 4 bayta ihtiyacınız olacak kadar yeterli kod noktasına sahiptir. UTF-32 kodlamasının yaptığı budur. Yine de UTF-8 kodlaması, "değişken genişlikli kodlama" adı verilen bir şey kullanarak bunları bir şekilde çok daha küçük alanlara sıkıştırır.

Aslında, US-ASCII'nin ilk 127 karakterini tam olarak gerçek ASCII'ye benzeyen tek bir baytta temsil etmeyi başarır, böylece pek çok ascii metnini, hiçbir şey yapmadan UTF-8miş gibi yorumlayabilirsiniz. Düzgün hile. Peki nasıl çalışıyor?

Burada kendi sorumu sorup cevaplayacağım çünkü anlamak için biraz okudum ve bunun başka birine biraz zaman kazandıracağını düşündüm. Artı belki bir kısmını yanlış anlarsam birisi beni düzeltebilir.


8
Düz Unicode yok değil tüm kod noktalarını kodlamak için 32 bit gerektirir. Bir zamanlar birçok olası kod noktasını iddia ettiler, ancak UTF-8 kalktıktan sonra, kendilerini kasıtlı olarak 21 bit ile sınırladılar, böylece UTF-8 hiçbir zaman karakter başına 4 baytı geçmeyecek. Unicode şu anda tüm olası kod noktalarını tutmak için yalnızca 17 bit gerektirir. Bu sınırlama olmadan, UTF-8 karakter başına 6 bayta çıkabilirdi.
Warren Young

@Warren: çoğunlukla doğrudur, ancak Unicode 21 bitlik bir koddur (U + 0000 - U + 10FFFF).
Jonathan Leffler

2
@Warren: 4 bayt sınırlı UTF-8, U + 1FFFFF'ye kadar destekleyebilirdi. UTF-16 uğruna U + 10FFFF kısıtlaması yapılmıştır.
dan04

@ dan04 UTF-16 tarafından U + 10FFFF ile nasıl sınırlandırıldığına dair herhangi bir kolay açıklamamız var mı? Bununla ilgili daha fazla bilgi sahibi olmak güzel olurdu.
A-letubby

@ A-letubby: UTF-16 "vekil" kodları, 2 ^ 20 (yaklaşık bir milyon) ek karakter oluşturmak için 1024 öncü vekil ve 1024 iz vekili olacak şekilde tahsis edildiğinden (ve bunlar yalnızca çiftler halinde kullanılabilir) BMP'nin ötesinde mevcuttur. BMP'de bulunan 2 ^ 16 karaktere eklendiğinde, bu 0x110000 olası karakterleri oluşturur.
dan04

Yanıtlar:


129

Her bayt, tek baytlı bir kod noktası mı, çok baytlı bir kod noktası mı yoksa çok baytlı bir kod noktasının devamı mı olduğunu size söyleyen birkaç bitle başlar. Bunun gibi:

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

Çok baytlı kod noktalarının her biri, aslında "hey, ne olduğumu anlamak için bir sonraki baytı (veya iki veya üç) okumalısın" diyen birkaç bitle başlar. Onlar:

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

Son olarak, bu başlangıç ​​kodlarını takip eden baytların tümü şuna benzer:

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

İlk birkaç bitten ne tür bir bayta baktığınızı anlayabildiğiniz için, o zaman bir yerde bir şey karıştırılsa bile, tüm diziyi kaybetmezsiniz.


14
Hikayede bundan daha fazlası var - çünkü kodlama karakter için mümkün olan en kısa kodlama olmalıdır, bu da örneğin 0xC0 ve 0xC1 baytlarının UTF-8'de görünemeyeceği anlamına gelir; ve aslında, 0xF5..0xFF de olamaz. UTF-8 SSS bölümüne bakın: unicode.org/faq/utf_bom.html veya unicode.org/versions/Unicode5.2.0/ch03.pdf
Jonathan Leffler

2
Neden söylemek için tek bir karakter kullanamadı next char is continuation? Eğer 3 baytlık karakter elde edersek, o zaman şöyle olur:, 1xxxxxxx 1xxxxxxx 0xxxxxxxyani daha az yer israf olur.

9
@Soaku, UTF-8'i "kendi kendini senkronize eden" bir kod yapar. Bu, eğer hatalar nedeniyle dizinin bazı kısımları eksikse, bunu tespit etmenin ve bozuk olanı atmanın mümkün olduğu anlamına gelir. 10xx ile başlayan bir bayt okursanız ve önünde "başlangıç" baytı yoksa, anlamsız olduğu için onu atabilirsiniz. Tanımladığınız gibi bir sisteminiz varsa ve ilk baytlardan biri kaybolursa, herhangi bir hata belirtisi olmayan farklı, geçerli bir karakterle karşılaşabilirsiniz. Ayrıca, bir sonraki geçerli karakteri bulmayı ve eksik "devam" baytlarını düzeltmeyi kolaylaştıracaktır.
htmlcoderexe

9

RFC3629 - UTF-8, ISO 10646 dönüştürme formatı burada nihai ve tüm açıklamalara sahiptir.

Kısacası, UTF-8 ile kodlanmış 1-4 bayt dizisinin her bir baytında bulunan ve tek bir karakteri temsil eden birkaç bit, bunun bir sondaki bayt mı, bir ön bayt mı olduğunu ve eğer öyleyse, kaç bayt olduğunu belirtmek için kullanılır. Kalan bitler yükü içerir.


1
Ummmm, aptalca ben, Unicode Standardının UTF-8 üzerindeki nihai otorite olduğunu düşündüm
John Machin

6
Unicode standardı, Unicode'un kendisini tanımlar. Unicode metinleri çeşitli amaçlarla (depolama ve taşıma gibi) kodlamak için kullanılabilecek, bugünün ve geleceğin çeşitli yöntemlerini tanımlamaz. UTF-8 bu yöntemlerden biridir ve yukarıdaki referans, onu tanımlayan belgeye ilişkindir.
azheglov

1
RFC3629, sayfa 3, bölüm 3. "UTF-8 Unicode Standardı tarafından tanımlanmıştır" diyor.
John Machin

Unicode.org'daki bağlantıları takip etmek beni Unicode Standardının 3.9 bölümüne ve özellikle D92 (ve ayrıca teğetsel olarak D86) tanımına götürdü . Yeni sürümler yayınlandığında bu bağlantının ne ölçüde yararlı olacağı hakkında hiçbir fikrim yok, ancak bölüm ve tanım tanımlayıcılarını sürümler arasında sabit tutmak istediklerini tahmin ediyorum.
üçlü

4

UTF-8, Unicode kod noktaları dizinizi, bu sihirli U + sayılarını 8 bit bayt kullanarak bellekte depolamak için başka bir sistemdi. UTF-8'de, 0-127 arasındaki her kod noktası tek bir baytta saklanır. Yalnızca 128 ve üstü kod noktaları 2, 3 kullanılarak, aslında 6 bayta kadar depolanır.

Mutlak Minimumdan Alıntı Her Yazılım Geliştiricisi Kesinlikle Unicode ve Karakter Kümeleri Hakkında Bilmeli (Mazeret Yok!)


Bu iyi bir makale, ama görünen o ki Joel dizinin maksimum uzunluğu konusunda yanılıyor; Wikipedia sayfası yalnızca karakter başına 1..4 bayt gösterir.
gevşeyin

4
Yukarıda da söylediğim gibi, UTF-8 ilk oluşturulduğunda, Unicode kod noktaları için 32 bitlik iddiada bulunuyordu, gerçekten buna ihtiyaç duydukları için değil, sadece 32 bit uygun bir değer olduğu ve çoktan aşmış oldukları için önceki 16 bitlik karakter sınırı. UTF-8 popüler olduktan sonra, maksimum kod noktası sayısını sonsuza kadar 2 ^ 21 ile sınırlamayı seçtiler; bu, UTF-8 şemasının 4 baytıyla kodlayabileceğiniz en büyük değerdir. Unicode'da hala 2 ^ 17'den az karakter var, bu nedenle bu yeni şema ile Unicode'daki karakter sayısını dört kattan fazla artırabiliriz.
Warren Young

Tamam ama OP'nin sorduğu açıklama değil.
Nishant

2
Bu soruya cevap vermiyor.
Koray Tugay
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.