2009-10-09 12 views
76

Standardowy kod Unicode zawiera wystarczającą liczbę punktów kodowych, które wymagają 4 bajtów do zapisania wszystkich. To właśnie robi kodowanie UTF-32. Jednak kodowanie UTF-8 w jakiś sposób wyciska je na znacznie mniejsze przestrzenie, używając czegoś, co nazywa się "kodowaniem o zmiennej szerokości".Jak działa kodowanie o zmiennej szerokości UTF-8?

Udaje mu się przedstawić pierwsze 127 znaków US-ASCII w jednym bajcie, który wygląda dokładnie tak, jak w prawdziwym ASCII, dzięki czemu można interpretować wiele tekstów ASCII tak, jakby były w formacie UTF-8, nie robiąc przy tym niczego . Sztuczka. Jak to działa?

Zamierzam zapytać i odpowiedzieć na moje własne pytanie, ponieważ po prostu trochę czytałem, aby to zrozumieć i pomyślałem, że może to kiedyś uratować kogoś innego. Plus może ktoś może mnie poprawić, jeśli coś jest nie tak.

+7

Prosty kod Unicode * nie * wymaga 32 bitów do zakodowania wszystkich punktów kodowych. Kiedyś zgłosili roszczenie do wielu możliwych punktów kodowych, ale po uruchomieniu UTF-8 celowo ograniczyli się do 21 bitów, więc UTF-8 nigdy nie przekroczy 4 bajtów na znak. Unicode wymaga obecnie tylko 17 bitów do przechowywania wszystkich możliwych punktów kodowych. Bez tego ograniczenia, UTF-8 mógł przejść do 6 bajtów na znak. –

+0

@Warren: w większości dokładne, ale Unicode to 21-bitowy kod (U + 0000 do U + 10FFFF). –

+2

@Warren: Limit 4-bajtowy UTF-8 mógł obsłużyć do U + 1FFFFF. Ograniczenie do U + 10FFFF zostało wprowadzone ze względu na UTF-16. – dan04

Odpowiedz

94

Każdy bajt zaczyna się od kilku bitów, które informują o tym, czy jest to kod bajtowy z jednym bajtem, wielobajtowy punkt kodowy czy kontynuacja wielobajtowego punktu kodowego. Tak:

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

Multi-bajtowych kodów punktów każdy zacząć od kilku bitów, które zasadniczo powiedzieć „hej, trzeba też przeczytać następny bajt (lub dwa, lub trzy), aby dowiedzieć się, kim jestem . " Są to:

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

Wreszcie, bajty, które następują te wszystkie kody zaczynają wyglądać tak:

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

Ponieważ można powiedzieć, jakiego rodzaju bajt patrzysz od kilku pierwszych bitów, wtedy nawet jeśli coś zostanie gdzieś zmasakrowane, nie tracisz całej sekwencji.

+12

Więcej historii niż to - ponieważ kodowanie musi być najkrótszym możliwym kodowaniem dla znaku, co kończy się znaczeniem, że bajty 0xC0 i 0xC1 nie mogą pojawić się na przykład w UTF-8; i tak naprawdę nie można też 0xF5..0xFF. Zobacz FAQ UTF-8 na http://unicode.org/faq/utf_bom.html lub http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf –

+0

Dlaczego nie można użyć tylko jednego char powiedzieć "następny znak to kontynuacja"? Jeśli mamy znak 3-bajtowy, będzie to wyglądało tak: '1xxxxxxx 1xxxxxxx 0xxxxxxx', więc mniej miejsca zostanie zmarnowane. – Soaku

+1

@Soaku sprawia, że ​​UTF-8 jest tak zwanym "samo synchronizującym się" kodem. Oznacza to, że jeśli z powodu błędów brakuje części sekwencji, można to wykryć i odrzucić to, co zostało zniekształcone. Jeśli czytasz bajt rozpoczynający się od 10xx i nie ma poprzedzającego bajtu "startu", możesz go odrzucić, ponieważ nie ma on znaczenia. Gdybyś miał system taki, jak opisałeś, a jeden z pierwszych bajtów zostałby utracony, mógłbyś otrzymać inną, prawidłową postać bez wskazania jakiegokolwiek błędu. Ułatwi to również zlokalizowanie następnego poprawnego znaku, jak również poprawienie brakujących bajtów "kontynuacja". – htmlcoderexe

1

UTF-8 był inny system do przechowywania swój ciąg Unicode punktów kodowych, te magiczne numery + U, w pamięci pomocą 8-bitowych bajtów. W UTF-8 każdy kod o kodzie od 0-127 jest przechowywany w pojedynczym bajcie . Tylko punkty kodowe 128 i powyżej są przechowywane za pomocą 2, 3, w rzeczywistości do 6 bajtów.

Fragment The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

+0

To dobry artykuł, ale wygląda na to, że Joel myli się co do maksymalnej długości sekwencji; strona Wikipedia pokazuje tylko 1..4 bajty na znak. – unwind

+4

Jak już wspomniałem powyżej, kiedy UTF-8 został po raz pierwszy utworzony, Unicode roszczą sobie prawo do 32-bitowych punktów kodowych, nie dlatego, że naprawdę tego potrzebowali, tylko dlatego, że 32-bitowe wartości są wygodną wartością i już minęły poprzedni limit 16-bitowych znaków. Po tym, jak UTF-8 okazał się popularny, postanowili na zawsze ograniczyć maksymalną liczbę punktów kodowych do 2^21, która jest największą wartością, jaką można zakodować za pomocą 4 bajtów schematu UTF-8. W Unicode wciąż jest mniej niż 2^17 znaków, więc możemy więcej niż czterokrotnie zwiększyć liczbę znaków w Unicode z tym nowym schematem. –

+0

Dobrze, ale nie wyjaśnienia, które stawia OP. – Nishant

7

RFC3629 - UTF-8, a transformation format of ISO 10646 jest ostatecznym autorytetem tutaj i ma wszelkie wyjaśnienia.

W skrócie, kilka bitów w każdym bajcie sekwencji 1 do 4 bajtów zakodowanych w UTF, reprezentujących pojedynczy znak, służy do wskazania, czy jest to bajt kończący, bajt wiodący, a jeśli tak, to w jaki sposób wiele bajtów. Pozostałe bity zawierają ładunek.

+1

Ummmm, głuptasie, myślałem, że standard Unicode był ostateczną autoryzacją na UTF-8 –

+6

Standard Unicode definiuje sam Unicode. Nie definiuje różnych metod, dzisiejszych i przyszłych, które mogą być używane do kodowania tekstów unicode dla różnych celów (takich jak przechowywanie i transport). UTF-8 jest jedną z tych metod, a powyższe odwołanie odnosi się do dokumentu, który ją definiuje. – azheglov

+0

RFC3629, strona 3, sekcja 3. mówi "UTF-8 jest zdefiniowany przez standard Unicode". –