Jaka jest maksymalna liczba bajtów na jeden znak zakodowany w UTF-8?
Będę szyfrować bajty String zakodowanego w UTF-8 i dlatego muszę być w stanie obliczyć maksymalną liczbę bajtów dla String zakodowanego w UTF-8.
Czy ktoś mógłby potwierdzić maksymalną liczbę bajtów dla pojedynczego znaku zakodowanego w UTF-8?
Odpowiedzi:
Maksymalna liczba bajtów na znak to 4 zgodnie z RFC3629, który ogranicza tablicę znaków do
U+10FFFF
:(Oryginalna specyfikacja dopuszczała maksymalnie sześciobajtowe kody znaków dla poprzednich punktów kodowych
U+10FFFF
).Znaki z kodem mniejszym niż 128 będą wymagały tylko 1 bajtu, a następne kody 1920 znaków będą wymagały tylko 2 bajtów. Jeśli nie pracujesz z językiem ezoterycznym, pomnożenie liczby znaków przez 4 będzie znacznym przeszacowaniem.
źródło
11111111
i2^(6*7)
trochę miejsca na znaki?Bez dalszego kontekstu powiedziałbym, że maksymalna liczba bajtów na znak w UTF-8 to
odpowiedź: 6 bajtów
Autor zaakceptowanej odpowiedzi poprawnie wskazał to jako „specyfikację oryginalną”. Było to ważne przez RFC-2279 1 . Jak zauważył J. Cocoe w komentarzach poniżej, zmieniło się to w 2003 r. Wraz z RFC-3629 2 , który ogranicza kodowanie UTF-8 do 21 bitów, które można obsługiwać za pomocą schematu kodowania wykorzystującego cztery bajty.
odpowiedz, jeśli obejmuje cały Unicode: 4 bajty
Ale w Javie <= v7 mówią o maksimum 3 bajtów do reprezentowania Unicode z UTF-8? Dzieje się tak, ponieważ oryginalna specyfikacja Unicode definiowała tylko podstawową płaszczyznę wielojęzyczną ( BMP ), tj. Jest to starsza wersja Unicode lub podzbiór współczesnego Unicode. Więc
odpowiedź, jeśli reprezentuje tylko oryginalny Unicode, BMP: 3 bajty
Ale OP mówi o pójściu w drugą stronę. Nie od znaków do bajtów UTF-8, ale od bajtów UTF-8 do „Ciągu” reprezentacji bajtów. Być może autor przyjętej odpowiedzi wyciągnął to z kontekstu pytania, ale niekoniecznie jest to oczywiste, więc może zdezorientować przypadkowego czytelnika tego pytania.
Przechodząc od kodowania UTF-8 do kodowania natywnego, musimy przyjrzeć się, jak zaimplementowano „ciąg znaków”. Niektóre języki, takie jak Python> = 3, będą reprezentować każdy znak za pomocą całkowitych punktów kodowych, co pozwala na 4 bajty na znak = 32 bity na pokrycie 21 potrzebnych nam dla Unicode, z pewnymi stratami. Dlaczego nie dokładnie 21 bitów? Ponieważ rzeczy są szybsze, gdy są wyrównane do bajtów. Niektóre języki, takie jak Python <= 2 i Java, reprezentują znaki przy użyciu kodowania UTF-16, co oznacza, że muszą używać par zastępczych do reprezentowania rozszerzonego Unicode (nie BMP). Tak czy inaczej, to nadal maksymalnie 4 bajty.
odpowiedź, jeśli przechodzisz do UTF-8 -> kodowanie natywne: 4 bajty
Tak więc, ostateczny wniosek, 4 to najczęstsza prawidłowa odpowiedź, więc mamy rację. Ale przebieg może się różnić.
źródło
1F FF FF
lub 21 bitach. Liczba 0x110000 odpowiada 17 płaszczyznom punktów kodowych 0x10000 każda.Maksymalna liczba bajtów do obsługi US-ASCII, standardowego kodowania alfabetu angielskiego, to 1. Jednak ograniczanie tekstu do języka angielskiego staje się coraz mniej pożądane lub praktyczne w miarę upływu czasu.
Unicode został zaprojektowany, aby reprezentować glify wszystkich języków ludzkich, a także wiele rodzajów symboli z różnymi cechami renderowania. UTF-8 jest wydajnym kodowaniem dla Unicode, chociaż nadal jest nastawiony na angielski. UTF-8 jest samosynchronizujący: granice znaków można łatwo zidentyfikować poprzez skanowanie w poszukiwaniu dobrze zdefiniowanych wzorów bitowych w dowolnym kierunku.
Podczas gdy maksymalna liczba bajtów na znak UTF-8 wynosi 3 dla obsługi tylko 2-bajtowej przestrzeni adresowej Plane 0, Basic Multilingual Plane (BMP), która może być zaakceptowana jako minimalne wsparcie w niektórych aplikacjach, to 4 dla obsługi wszystkie 17 aktualnych płaszczyzn Unicode (stan na 2019). Należy zauważyć, że wiele popularnych znaków "emoji" prawdopodobnie znajduje się w Płaszczyźnie 16, która wymaga 4 bajtów.
Jednak dotyczy to tylko podstawowych glifów znaków. Istnieją również różne modyfikatory, takie jak umieszczanie akcentów na poprzednim znaku, a także możliwe jest połączenie dowolnej liczby punktów kodowych w celu zbudowania jednego złożonego „grafemu”. Dlatego w programowaniu w świecie rzeczywistym użycie lub założenie stałej maksymalnej liczby bajtów na znak prawdopodobnie ostatecznie doprowadzi do problemu z aplikacją.
Z tych rozważań wynika, że ciągi znaków UTF-8 nie powinny być „rozszerzane” do tablic o stałej długości przed przetwarzaniem, jak to czasami robiono. Zamiast tego programowanie powinno odbywać się bezpośrednio, przy użyciu funkcji napisów zaprojektowanych specjalnie dla UTF-8.
źródło