Jestem trochę zdezorientowany co do kodowania. O ile wiem, stare znaki ASCII zajmowały jeden bajt na znak. Ile bajtów wymaga znak Unicode?
Zakładam, że jeden znak Unicode może zawierać każdy możliwy znak z dowolnego języka - czy mam rację? Ile bajtów potrzebuje na znak?
A co oznaczają UTF-7, UTF-6, UTF-16 itd.? Czy są to różne wersje Unicode?
Czytałem artykuł w Wikipedii o Unicode, ale jest to dla mnie dość trudne. Nie mogę się doczekać prostej odpowiedzi.
Odpowiedzi:
Nie zobaczysz prostej odpowiedzi, ponieważ nie ma takiej.
Po pierwsze, Unicode nie zawiera „wszystkich znaków z każdego języka”, chociaż na pewno próbuje.
Sam Unicode jest odwzorowaniem, definiuje punkty kodowe, a punkt kodowy jest liczbą związaną zwykle ze znakiem. Mówię zwykle, ponieważ istnieją pojęcia takie jak łączenie postaci. Możesz być zaznajomiony z akcentami lub umlautami. Można ich użyć z innym znakiem, takim jak a
a
lub a,u
aby utworzyć nowy znak logiczny. Postać może zatem składać się z 1 lub więcej współrzędnych kodowych.Aby być użytecznym w systemach komputerowych, musimy wybrać reprezentację dla tych informacji. Są to różne kodowania Unicode, takie jak utf-8, utf-16le, utf-32 itd. Różnią się one w dużej mierze rozmiarem ich jednostek kodowych. UTF-32 jest najprostszym kodowaniem, ma 32-bitową jednostkę kodową, co oznacza, że pojedynczy punkt kodowy wygodnie pasuje do jednostki kodowej. Inne kodowania będą miały sytuacje, w których punkt kodowy będzie wymagał wielu jednostek kodowych lub ten konkretny punkt kodowy nie będzie w ogóle reprezentowany w kodowaniu (jest to na przykład problem z UCS-2).
Ze względu na elastyczność łączenia znaków, nawet w ramach danego kodowania, liczba bajtów na znak może się różnić w zależności od znaku i formy normalizacji. Jest to protokół postępowania ze znakami, które mają więcej niż jedną reprezentację (możesz powiedzieć,
"an 'a' with an accent"
które są 2 kodowymi punktami, z których jeden jest znakiem łączącym lub"accented 'a'"
który jest jednym kodowym).źródło
O dziwo, nikt nie wskazał, jak obliczyć, ile bajtów zajmuje jeden znak Unicode. Oto reguła dla łańcuchów kodowanych w UTF-8:
Szybka odpowiedź brzmi: zajmuje 1 do 4 bajtów, w zależności od pierwszego, który wskaże, ile bajtów zajmie.
źródło
Wiem, że to pytanie jest stare i ma już zaakceptowaną odpowiedź, ale chcę podać kilka przykładów (mam nadzieję, że będzie komuś przydatny).
Dobrze. W rzeczywistości, ponieważ ASCII jest kodowaniem 7-bitowym, obsługuje 128 kodów (z których 95 można wydrukować), więc wykorzystuje tylko pół bajtu (jeśli to ma sens).
Unicode po prostu mapuje znaki na punkty kodowe. Nie określa, jak je zakodować. Plik tekstowy nie zawiera znaków Unicode, ale bajty / oktety, które mogą reprezentować znaki Unicode.
Nie. Ale prawie. W zasadzie tak. Ale nadal nie.
To samo co twoje drugie pytanie.
Nie, to są kodowania. Określają, w jaki sposób bajty / oktety powinny reprezentować znaki Unicode.
Kilka przykładów. Jeśli niektórych z nich nie można wyświetlić w przeglądarce (prawdopodobnie dlatego, że czcionka ich nie obsługuje), przejdź do
http://codepoints.net/U+1F6AA
(zamień1F6AA
na współrzędną kodową w hex), aby zobaczyć obraz.a
©
®
ጷ
—
‰
€
™
☃
☎
☔
☺
⚑
⚛
✈
✞
〠
肉
💩
🚀
Dobra, daję się ponieść ...
Zabawne fakty:
źródło
00A9
zamiast00 A9
(która byłaby UTF-16BE).Mówiąc wprost,
Unicode
jest standardem, który przypisuje jeden numer (zwany punktem kodowym) wszystkim postaciom świata (wciąż trwa).Teraz musisz reprezentować ten kod za pomocą bajtów, tak zwanych
character encoding
.UTF-8, UTF-16, UTF-6
to sposoby reprezentowania tych postaci.UTF-8
to wielobajtowe kodowanie znaków. Znaki mogą mieć od 1 do 6 bajtów (niektóre z nich mogą być w tej chwili niepotrzebne).UTF-32
każdy znak ma 4 bajty na znak.UTF-16
używa 16 bitów na każdy znak i reprezentuje tylko część znaków Unicode o nazwie BMP (dla wszystkich praktycznych celów wystarczy). Java używa tego kodowania w swoich ciągach.źródło
W UTF-8:
W UTF-16:
W UTF-32:
10FFFF jest ostatnim kodem Unicode z definicji i jest zdefiniowany w ten sposób, ponieważ jest to limit techniczny UTF-16.
Jest to również największy punkt kodowy UTF-8, który może kodować w 4 bajtach, ale idea kodowania UTF-8 działa również w przypadku kodowania 5 i 6 bajtów, aby pokryć punkty kodowe do 7FFFFFFF, tj. połowa tego, co potrafi UTF-32.
źródło
W Unicode odpowiedź nie jest łatwa. Problem, jak już wskazałeś, polega na kodowaniu.
Biorąc pod uwagę dowolne zdanie w języku angielskim bez znaków diakrytycznych, odpowiedź dla UTF-8 będzie miała tyle bajtów, ile znaków, a dla UTF-16 będzie to liczba znaków dwa razy.
Jedynym kodowaniem, w którym (na razie) możemy wypowiedzieć się na temat rozmiaru, jest UTF-32. Tam zawsze jest 32 bity na znak, chociaż wyobrażam sobie, że punkty kodowe są przygotowane na przyszły UTF-64 :)
To, co czyni to tak trudnym, to co najmniej dwie rzeczy:
U+20AC
może być reprezentowany jako sekwencja trzy bajtowaE2 82 AC
lub sekwencja czterobajtowaF0 82 82 AC
.źródło
Istnieje świetne narzędzie do obliczania bajtów dowolnego ciągu w UTF-8: http://mothereff.in/byte-counter
Aktualizacja: @mathias podał kod do wiadomości publicznej: https://github.com/mathiasbynens/mothereff.in/blob/master/byte-counter/eff.js
źródło
Cóż, właśnie podciągnąłem na nim stronę Wikipedii, aw części wstępnej zobaczyłem, że „Unicode może być implementowany za pomocą różnych kodowań znaków. Najczęściej stosowanymi kodowaniami są UTF-8 (który używa jednego bajtu dla dowolnych znaków ASCII, które mają te same wartości kodu zarówno w kodowaniu UTF-8, jak i ASCII oraz do czterech bajtów dla innych znaków, obecnie nieaktualny UCS-2 (który używa dwóch bajtów dla każdego znaku, ale nie może zakodować wszystkich znaków w bieżącym standardzie Unicode) ”
Jak pokazuje ten cytat, twoim problemem jest to, że zakładasz, że Unicode jest jednym ze sposobów kodowania znaków. W rzeczywistości istnieje wiele form Unicode, i znowu w tym cytacie, jeden z nich ma nawet 1 bajt na znak, tak jak przywykłeś.
Tak więc twoją prostą odpowiedzią jest to, że jest różna.
źródło
W przypadku UTF-16 znak potrzebuje czterech bajtów (dwóch jednostek kodu), jeśli zaczyna się od 0xD800 lub większej; taka postać nazywa się „parą zastępczą”. Mówiąc dokładniej, para zastępcza ma postać:
gdzie [...] oznacza dwubajtową jednostkę kodu o podanym zakresie. Wszystko <= 0xD7FF to jedna jednostka kodu (dwa bajty). Wszystko> = 0xE000 jest nieprawidłowe (z wyjątkiem znaczników BOM, prawdopodobnie).
Zobacz http://unicodebook.readthedocs.io/unicode_encodings.html , sekcja 7.5.
źródło
Sprawdź ten konwerter kodu Unicode . Na przykład wpisz
0x2009
, gdzie 2009 to numer Unicode dla cienkiej przestrzeni , w polu „0x ... notacja” i kliknij Konwertuj. Liczba szesnastkowaE2 80 89
(3 bajty) pojawia się w polu „Jednostki kodu UTF-8”.źródło
Z Wiki:
Są to trzy najpopularniejsze różne kodowania.
źródło
Unicode
to standard, który zapewnia unikalny numer dla każdej postaci. Te unikalne numery są nazywanecode point
s (co jest po prostu unikalnym kodem) dla wszystkich znaków istniejących na świecie (niektóre z nich są jeszcze do dodania).Do różnych celów może być konieczne przedstawienie tego
code points
w bajtach (większość języków programowania to robi), a oto gdzieCharacter Encoding
zaczyna.UTF-8
,UTF-16
,UTF-32
I tak dalej, to wszystkoCharacter Encodings
, a punkty kodowe Unicode są reprezentowane w tych kodowań, na różne sposoby.UTF-8
kodowanie ma zmienną szerokość, a zakodowane w nim znaki mogą zajmować od 1 do 4 bajtów włącznie;UTF-16
ma zmienną długość, a zakodowane w nim znaki mogą zająć 1 lub 2 bajty (czyli 8 lub 16 bitów). Reprezentuje to tylko część wszystkich znaków Unicode o nazwie BMP (Basic Multilingual Plane) i wystarcza na prawie wszystkie przypadki. Java używaUTF-16
kodowania dla swoich ciągów znaków i znaków;UTF-32
ma ustaloną długość, a każdy znak zajmuje dokładnie 4 bajty (32 bity).źródło