2012-03-02 11 views
54

Jaka jest maksymalna liczba bajtów dla jednego zakodowanego znaku UTF-8?Jaka jest maksymalna liczba bajtów dla znaków zakodowanych w UTF-8?

będę zaszyfrowanie bajtów napisu zakodowany w UTF-8 i dlatego muszą być w stanie pracować z maksymalną liczbę bajtów dla UTF-8 zakodowany ciąg.

Może ktoś potwierdzić maksymalną liczbę bajtów dla pojedynczego kodowanie UTF-8 znaku proszę

+1

Udało Ci się * spojrzeć na wspólne zasoby, takie jak [artykuł Wikipedii UTF-8] (http://en.wikipedia.org/wiki/UTF-8), najpierw ... prawda? –

+3

Przeczytałem kilka artykułów, które dały mieszane odpowiedzi ... Naprawdę odniosłem wrażenie, że odpowiedź była 3, więc bardzo się cieszę, że zapytałem – Edd

+1

Zostawię tu link youtube, zawierający postacie Toma Scotta, symbole, cud Unicode: https: //goo.gl/sUr1Hf. Usłyszysz i zobaczysz, jak wszystko ewoluuje od kodowania znaków ASCII do utf-8. – Roylee

Odpowiedz

61

Maksymalna liczba bajtów na znak jest 4 według RFC3629 ograniczający tabeli znaków do U+10FFFF:

W UTF-8 znaki z zakresu U + 0000..U + 10FFFF (zakres dostępny dla UTF-16 ) są kodowane przy użyciu sekwencji od 1 do 4 oktetów.

(Oryginalny opis pozostawiono do sześciu bajtu kodów znakowych dla punktów kodowych ostatnich U+10FFFF).

znaków kodem mniej niż 128 wymagają tylko 1 bajt, a następny 1920 kody znakowe wymagają 2 tylko bajty. Jeśli nie używasz ezoterycznego języka, pomnożenie liczby znaków przez 4 będzie znaczącym przeszacowaniem.

+2

Co to jest "język esoteryczny" dla Ciebie? Jakikolwiek język, który mógłby istnieć w świecie realnym, lub tekst, który przełącza się pomiędzy różnymi językami świata? Czy programista funkcji UTF-8-string musi wybrać 2, 3 lub 4 jako multiplikator, jeśli wykonuje nadmierną alokację i zmniejsza wynik po rzeczywistej konwersji? –

+1

@rinntech według "języka ezoterycznego" oznacza język, który ma wiele znaków o wysokiej wartości Unicode (coś z dolnej części tej listy: http://unicode-table.com/en/sections/). Jeśli musisz przesadzić, wybierz 4. Możesz wykonać podwójne przejście, jedno, aby zobaczyć, ile bajtów potrzebujesz i przydzielić, a następnie drugie do kodowania; to może być lepsze niż przydzielenie ~ 4 razy potrzebnej pamięci RAM. – matiu

+4

Zawsze staram się radzić w najgorszym przypadku: http://www.hacker9.com/single-message-can-crash-whatsapp.html –

22

Bez dalszego kontekście chciałbym powiedzieć, że maksymalna liczba bajtów na postać w UTF-8 jest

odpowiedź: 6 bajtów

Autor przyjętej odpowiedzieć poprawnie wskazywał na to, jak " oryginalna specyfikacja ", ale myślę, że to wprowadza w błąd czytelnika, ponieważ o ile mi wiadomo, jest to nadal aktualna i prawidłowa specyfikacja, za wikipedia, i za a Google book on UTF-8 in Java.

RFC mowa w przyjętych państw odpowiedź, że tylko cztery bajty są istotne dla kodowania UTF-16, tak że jest prawidłowa tylko jeśli dodamy kontekstowe

odpowiedź, jeśli tłumaczenia tylko znaki z UTF-16 do UTF- 8: 4 bajty

Teraz, czy wszystkie znaki, które mogą być reprezentowane przez UTF-16, są użyteczne? Według wikipedia again, kodowanie Unicode może wynosić do punktów kodowych x10FFFF. Zatem, w tym 0, oznacza to, że możemy to zrobić za pomocą tych bajtów: F FF FF, tj. Dwa i pół bajty lub 20 bitów. Patrząc wstecz na specyfikację UTF-8 widzimy, że możemy reprezentować 20 bitów z maksymalnie czterema bajtami zakodowanymi w UTF-8. Więc

odpowiedź jeśli obejmujące wszystkie unicode: 4 bajty

Ale w Java <= v7, mówią o maksymalnie 3 bajtów do reprezentowania Unicode UTF-8? Wynika to z faktu, że oryginalna specyfikacja unikodu definiowała tylko podstawową płaszczyznę wielojęzyczną (BMP), tj. Jest starszą wersją unikodu lub podzbiorem nowoczesnego unicodu. Więc

odpowiedź, jeśli stanowią jedynie oryginalne Unicode, BMP: 3 bajty

Ale PO mówi o idzie w drugą stronę. Nie od znaków do bajtów UTF-8, ale od bajtów UTF-8 do "String" reprezentacji bajtów. Być może autor przyjętej odpowiedzi zrozumiał to z kontekstu pytania, ale niekoniecznie jest to oczywiste, więc może zmylić przypadkowego czytelnika tego pytania.

Przechodząc z UTF-8 do kodowania natywnego, musimy sprawdzić, w jaki sposób implementowany jest "łańcuch znaków". Niektóre języki, takie jak Python> = 3, będą reprezentowały każdy znak z liczbą całkowitą punktów kodowych, co pozwala na 4 bajty na znak = 32 bity, aby pokryć 20, które potrzebujemy do unicodu, z pewnymi stratami. Dlaczego nie dokładnie 20 bitów? Ponieważ rzeczy są szybsze, gdy są wyrównane do bajtu. Niektóre języki, takie jak Python < = 2 i Java, reprezentują znaki przy użyciu kodowania UTF-16, co oznacza, że ​​muszą używać zastępczych par reprezentujących rozszerzony kod Unicode (nie BMP). Tak czy inaczej nadal 4 bajty maksimum.

odpowiedź, jeśli idzie UTF-8 -> kodowanie natywne: 4 bajty

Tak, ostateczna konkluzja, 4 jest najczęstszą odpowiedzią prawo, więc mamy go w prawo. Ale w pewnych kontekstach powinieneś być ostrożny. Np. Nie oczekuj, że możesz reprezentować wszystko, co czytasz ze strumienia UTF-8 w maksymalnie 4 bajtach. Jeśli nie jest to kodowanie Unicode, możesz potrzebować do 6 bajtów.

+1

"to jest nadal aktualna i prawidłowa specyfikacja, na wikipedię" - już nie. Wkrótce po tym, jak to napisałeś (edycja 2 kwietnia), artykuł Wikipedii UTF-8 został zmieniony w celu wyjaśnienia, że ​​wersja 6-oktetowa nie jest częścią aktualnej (2003) specyfikacji UTF-8. –

+0

"Ale w Javie <= v7, mówią o 3-bajtowym maksimum do reprezentowania Unicode z UTF-8? To dlatego, że oryginalna specyfikacja Unicode zdefiniowała tylko podstawową płaszczyznę wielojęzyczną" - To prawdopodobnie pierwotny powód, ale to nie jest cała historia. Java używa "zmodyfikowanego UTF-8", a jedną z modyfikacji jest to, że "używa swojego własnego formatu dwa razy-trzy bajty" zamiast "czterobajtowego formatu standardowego UTF-8" (ich słowa). –

+0

Nie ma punktów kodowych przydzielonych powyżej limitu 10FFFF (nieco ponad milion) i wiele implementacji UTF8 nigdy nie implementowało sekwencji dłuższych niż 4 bajty (i niektóre tylko 3, np. MySQL), więc uważam, że bezpieczne jest ograniczenie do 4 bajtów na kod, nawet przy uwzględnieniu zgodności ze starszymi implementacjami. Trzeba po prostu upewnić się, że odrzucisz coś nieważnego po drodze. Pamiętaj, że zalecenie matiu dotyczące alokacji po obliczeniu dokładnej długości bajtów jest w miarę możliwości dobre. – thomasrutter