Rozumiem, że wszystkie będą przechowywać Unicode i że każdy używa innej liczby bajtów do przedstawienia znaku. Czy istnieje korzyść z wyboru jednego nad drugim?
Film koncentruje się na UTF-8 i tak, dobrze wyjaśnia, jak działa kodowanie o zmiennej długości i jest w większości kompatybilny z komputerami odczytującymi lub zapisującymi ASCII o stałej długości. Ludzie z Unicode byli sprytni przy projektowaniu kodowania UTF-8.
UTF-8 jest de facto standardem w najnowocześniejszym oprogramowaniu do zapisywania plików . Mówiąc dokładniej, jest to najczęściej stosowane kodowanie HTML oraz plików konfiguracyjnych i tłumaczeniowych (na przykład Minecraft nie akceptuje żadnego innego kodowania dla wszystkich informacji tekstowych). UTF-32 jest szybki do reprezentacji pamięci wewnętrznej , a UTF-16 jest trochę przestarzały , obecnie używany tylko w Win32 z powodów historycznych ( UTF-16 miał stałą długość, gdy Windows 95 był czymś)
Kotauskas
@VladislavToncharov UTF-16 nigdy nie był kodowaniem o stałej długości. Mylisz to z UCS-2.
Odpowiedzi:
373
UTF-8 ma tę zaletę, że znaki ASCII reprezentują większość znaków w bloku tekstu, ponieważ UTF-8 koduje je na 8 bitów (jak ASCII). Korzystne jest również to, że plik UTF-8 zawierający tylko znaki ASCII ma takie samo kodowanie jak plik ASCII.
UTF-16 jest lepszy tam, gdzie ASCII nie dominuje, ponieważ używa głównie 2 bajtów na znak. UTF-8 zacznie używać 3 lub więcej bajtów dla znaków wyższego rzędu, gdzie UTF-16 pozostaje na poziomie zaledwie 2 bajtów dla większości znaków.
UTF-32 obejmie wszystkie możliwe znaki w 4 bajtach. To sprawia, że jest dość wzdęty. Nie mogę wymyślić żadnej korzyści z jego używania.
Zaleta UTF-32: nie trzeba dekodować przechowywanych danych do 32-bitowego punktu kodowania Unicode, np. Do obsługi znak po znaku. Punkt kodowy jest już dostępny w tablicy / wektorze / ciągu.
richq
22
Łatwiej jest także parsować, jeśli (niech niebo ci pomoże) musisz ponownie wdrożyć koło.
Paul McMillan
24
Cóż, UTF-8 ma przewagę w transferach sieciowych - nie musisz się martwić o endianowość, ponieważ przesyłasz dane jeden bajt na raz (w przeciwieństwie do 4).
Tim Čas,
30
@richq W UTF-32 nie można obsługiwać znaków po znaku, ponieważ punkt kodowy nie zawsze odpowiada znakowi.
hamstergene,
4
Zaleta UTF-32: manipulowanie strunami jest prawdopodobnie szybsze w porównaniu do odpowiednika utf-8
Wes
331
W skrócie:
UTF-8: Kodowanie o zmiennej szerokości, kompatybilne wstecz z ASCII. Znaki ASCII (U + 0000 do U + 007F) zajmują 1 bajt, punkty kodowe U + 0080 do U + 07FF zajmują 2 bajty, punkty kodowe U + 0800 do U + FFFF zajmują 3 bajty, punkty kodowe U + 10000 do U + 10FFFF weź 4 bajty. Dobre dla tekstu angielskiego, nie tak dobre dla tekstu azjatyckiego.
UTF-16: Kodowanie o zmiennej szerokości. Punkty kodowe U + 0000 do U + FFFF zajmują 2 bajty, punkty kodowe U + 10000 do U + 10FFFF zajmują 4 bajty. Zły dla tekstu angielskiego, dobry dla tekstu azjatyckiego.
UTF-32: Kodowanie o stałej szerokości. Wszystkie punkty kodowe zajmują cztery bajty. Ogromny wieprz pamięci, ale szybki w obsłudze. Rzadko używane.
@spurrymoses: Mam na myśli wyłącznie ilość miejsca zajmowaną przez bajty danych. UTF-8 wymaga 3 bajtów na znak azjatycki, podczas gdy UTF-16 wymaga tylko 2 bajtów na znak azjatycki. To naprawdę nie jest poważny problem, ponieważ komputery mają obecnie mnóstwo pamięci w porównaniu do średniej ilości tekstu przechowywanego w pamięci programu.
Adam Rosenfield
12
UTF-32 nie jest już rzadko używany ... w systemach OSX i Linux wchar_tdomyślnie ma 4 bajty. gcc ma opcję, -fshort-wcharktóra zmniejsza rozmiar do 2 bajtów, ale psuje binarną kompatybilność ze standardowymi bibliotekami lib.
winny
9
@PandaWood ofcource UTF-8 może zakodować dowolny znak! Ale czy porównałeś zapotrzebowanie na pamięć do UTF-16? Wydaje się, że brakuje ci sensu!
Ustaman Sangat,
16
Gdyby ktoś powiedział, że UTF-8 „nie jest tak dobry dla tekstu azjatyckiego” w kontekście wszystkich formatów kodowania, w tym tych, które nie mogą zakodować Unicode, oczywiście byłoby to błędem. Ale to nie jest kontekst. Kontekst wymagań dotyczących pamięci wynika z faktu, że pytanie (i odpowiedź) porównuje UTF-8, UTF-16 i UTF-32, które wszystkie kodują tekst azjatycki, ale wykorzystują różne ilości pamięci / pamięci. Wynika z tego, że ich względna dobroć byłaby oczywiście całkowicie w kontekście wymagań dotyczących pamięci. „Not so good”! = „Not good”.
Paul Gregory
5
@McGafter: Oczywiście, że tak. Jeśli chcesz wiarygodności, idź prosto do pyska konia w Konsorcjum Unicode . Opis kodowania UTF- * znajduje się w rozdziale 2.5. Ale dla uzyskania prostego zrozumienia kodowania na wysokim poziomie stwierdzam, że artykuły z Wikipedii są znacznie bardziej dostępnym źródłem.
@Urkle jest technicznie poprawny, ponieważ mapowanie pełnego zakresu UTF32 / LE / BE obejmuje U-00200000 - U-7FFFFFFF, mimo że Unicode v6.3 kończy się na U-0010FFFF włącznie. Oto ładny podział na sposób kodowania / dekodowania
4
wykonać kopię zapasową odpowiednich części referencyjnych i ich źródeł?
n611x007
20
@ Nie, UTF-8 nie może mieć 5 lub 6 bajtów. Punkty kodu Unicode są ograniczone do 21 bitów, co ogranicza UTF-8 do 4 bajtów. (Można oczywiście rozszerzyć zasadę UTF-8 o kodowanie dowolnych dużych liczb całkowitych, ale nie byłby to Unicode.) Patrz RFC 3629.
rdb
11
Cytując Wikipedię: W listopadzie 2003 UTF-8 został ograniczony przez RFC 3629, aby dopasować się do ograniczeń kodowania znaków UTF-16: jawnie zabraniając punktów kodowych odpowiadających wysokim i niskim znakom zastępczym usunięto ponad 3% trzy bajtowych sekwencji , a kończąc na U + 10FFFF usunięto ponad 48% czterobajtowych sekwencji i wszystkich pięcio- i sześciobajtowych sekwencji.
Adam Calvet Bohl
79
Unicode definiuje pojedynczy ogromny zestaw znaków, przypisując jedną unikalną wartość całkowitą każdemu symbolowi graficznemu (jest to duże uproszczenie i tak naprawdę nie jest prawdą, ale jest wystarczająco blisko dla celów tego pytania). UTF-8/16/32 to po prostu różne sposoby kodowania tego.
W skrócie, UTF-32 używa 32-bitowych wartości dla każdego znaku. To pozwala im używać kodu o stałej szerokości dla każdego znaku.
UTF-16 domyślnie używa 16-bitów, ale daje to tylko 65 000 możliwych znaków, co jest dalekie od pełnego zestawu Unicode. Dlatego niektóre znaki używają par 16-bitowych wartości.
A UTF-8 domyślnie używa wartości 8-bitowych, co oznacza, że 127 pierwszych wartości są znakami jednobajtowymi o stałej szerokości (najbardziej znaczący bit służy do oznaczenia, że jest to początek sekwencji wielobajtowej, pozostawiając 7 bity dla rzeczywistej wartości znaku). Wszystkie pozostałe znaki są kodowane jako ciągi do 4 bajtów (jeśli pamięć służy).
To prowadzi nas do korzyści. Każda postać ASCII jest bezpośrednio kompatybilna z UTF-8, więc do aktualizacji starszych aplikacji, UTF-8 jest powszechnym i oczywistym wyborem. W prawie wszystkich przypadkach zużywa również najmniej pamięci. Z drugiej strony nie możesz dać żadnych gwarancji co do szerokości znaku. Może mieć szerokość 1, 2, 3 lub 4 znaków, co utrudnia manipulację łańcuchem.
UTF-32 jest przeciwny, zużywa najwięcej pamięci (każdy znak ma stałą szerokość 4 bajtów), ale z drugiej strony wiesz, że każda postać ma tę dokładną długość, więc manipulowanie ciągiem staje się znacznie prostsze. Możesz obliczyć liczbę znaków w ciągu po prostu na podstawie długości w bajtach ciągu. Nie możesz tego zrobić z UTF-8.
UTF-16 to kompromis. Pozwala większości znaków zmieścić się w 16-bitowej wartości o stałej szerokości. Tak długo, jak nie masz chińskich symboli, nut lub niektórych innych, możesz założyć, że każda postać ma szerokość 16 bitów. Zużywa mniej pamięci niż UTF-32. Ale jest pod pewnymi względami „najgorszy z obu światów”. Prawie zawsze zużywa więcej pamięci niż UTF-8, i nadal nie omija problemu, który nęka UTF-8 (znaki o zmiennej długości).
Wreszcie często pomocne jest po prostu skorzystanie z obsługi platformy. Windows używa UTF-16 wewnętrznie, więc w Windows jest to oczywisty wybór.
Linux różni się nieco, ale ogólnie używają UTF-8 do wszystkiego, co jest zgodne z Unicode.
Tak krótka odpowiedź: wszystkie trzy kodowania mogą kodować ten sam zestaw znaków, ale reprezentują każdy znak jako różne sekwencje bajtów.
Nie można powiedzieć, że Unicode przypisuje unikalną liczbę całkowitą do każdego symbolu graficznego . Przypisuje takie do każdego punktu kodowego, ale niektóre punkty kodowe są niewidocznymi znakami kontrolnymi , a niektóre symbole graficzne wymagają reprezentacji wielu punktów kodowych .
tchrist
15
@tchrist: tak, to niedokładne. Problem polega na tym, że aby dokładnie wyjaśnić Unicode, musisz napisać tysiące stron. Miałem nadzieję, że uda mi się poznać podstawową koncepcję wyjaśniającą różnicę między kodowaniami
@tchrist Mówiąc ściślej, możesz konstruować chińskie symbole z dostarczonych prymitywów (ale są one na tym samym wykresie, więc po prostu skończysz z użyciem nierealnej ilości miejsca - dysku lub pamięci RAM - do ich zakodowania) zamiast używania wbudowane.
Kotauskas
44
Unicode jest standardem, a o UTF-x można pomyśleć jako techniczną implementację do niektórych praktycznych celów:
UTF-8 - „ zoptymalizowany rozmiar ”: najlepiej nadaje się do danych opartych na znakach łacińskich (lub ASCII), zajmuje tylko 1 bajt na znak, ale rozmiar odpowiednio rośnie różnorodność symboli (w najgorszym przypadku może wzrosnąć do 6 bajtów na znak)
UTF-16 - „ balance ”: zajmuje minimum 2 bajty na znak, co jest wystarczające dla istniejącego zestawu języków głównego nurtu z ustalonym rozmiarem, aby ułatwić obsługę znaków (ale rozmiar jest wciąż zmienny i może wzrosnąć do 4 bajtów na znak )
UTF-32 - „ wydajność ”: umożliwia stosowanie prostych algorytmów w wyniku znaków o stałej wielkości (4 bajty), ale z wadą pamięci
«Języki głównego nurtu» nie takie popularne w wielu częściach świata ^^
tuxayo
2
UTF-16 jest w rzeczywistości zoptymalizowany pod kątem rozmiaru dla znaków innych niż ASCII. Ponieważ tak naprawdę zależy od tego, w jakich językach będzie używany.
tuxayo
@tuxayo całkowicie się zgadza, warto zauważyć zestawy znaków Hanzi i Kanji dla azjatyckiej części świata.
wieża
Powinna być najlepsza odpowiedź. Jest to zbyt poprawne, aby je tutaj pochować.
Michal Štein
28
Próbowałem w prosty sposób wyjaśnić moje posty na blogu .
UTF-32
wymaga 32 bitów (4 bajty) do zakodowania dowolnego znaku. Na przykład, aby przedstawić kodowy punkt „A” za pomocą tego schematu, musisz wpisać 65 w 32-bitowej liczbie binarnej:
00000000 00000000 00000000 01000001 (Big Endian)
Jeśli przyjrzysz się bliżej, zauważysz, że najbardziej odpowiednie siedem bitów jest w rzeczywistości tymi samymi bitami, gdy używasz schematu ASCII. Ale ponieważ UTF-32 jest schematem o stałej szerokości , musimy dołączyć trzy dodatkowe bajty. Oznacza to, że jeśli mamy dwa pliki zawierające tylko znak „A”, jeden jest zakodowany w formacie ASCII, a drugi w formacie UTF-32, ich rozmiar będzie wynosił odpowiednio 1 bajt i 4 bajty.
UTF-16
Wiele osób uważa, że ponieważ UTF-32 używa stałej bitowej 32 do reprezentowania punktu kodowego, UTF-16 ma stałą szerokość 16 bitów. ŹLE!
W UTF-16 punkt kodowy może być reprezentowany albo w 16 bitach, albo w 32 bitach. Ten schemat to system kodowania o zmiennej długości. Jaka jest przewaga nad UTF-32? Przynajmniej w przypadku ASCII rozmiar plików nie będzie 4-krotnie większy niż oryginał (ale nadal dwa razy), więc nadal nie jesteśmy kompatybilni wstecznie ASCII.
Ponieważ 7 bitów wystarcza do przedstawienia znaku „A”, możemy teraz używać 2 bajtów zamiast 4, takich jak UTF-32. Będzie to wyglądać jak:
00000000 01000001
UTF-8
Zgadłeś słusznie. W UTF-8 punkt kodowy może być reprezentowany przy użyciu 32, 16, 24 lub 8 bitów, a jako system UTF-16 jest to także system kodowania o zmiennej długości.
Wreszcie możemy przedstawić „A” w taki sam sposób, w jaki reprezentujemy go za pomocą systemu kodowania ASCII:
01001101
Mały przykład, w którym UTF-16 jest rzeczywiście lepszy niż UTF-8:
Rozważmy chińską literę „語” - jej kodowanie UTF-8 to:
11101000 10101010 10011110
Chociaż jego kodowanie UTF-16 jest krótsze:
10001010 10011110
Aby zrozumieć reprezentację i jej interpretację, odwiedź oryginalny post.
całkowicie samosynchronizujący np. upuszczony bajt z dowolnego miejsca w strumieniu uszkodzi co najwyżej jeden znak
prawie wszystkie języki europejskie są zakodowane w dwóch bajtach lub mniej na znak
UTF-16
musi zostać przeanalizowany ze znaną kolejnością bajtów lub odczytaniem znaku kolejności bajtów (BOM)
używa 2 lub 4 bajtów na znak
UTF-32
każdy znak ma 4 bajty
musi zostać przeanalizowany ze znaną kolejnością bajtów lub odczytaniem znaku kolejności bajtów (BOM)
UTF-8 będzie najbardziej efektywny pod względem miejsca, chyba że większość znaków pochodzi z przestrzeni znaków CJK (chińskiej, japońskiej i koreańskiej).
UTF-32 najlepiej nadaje się do losowego dostępu poprzez przesunięcie znaków w tablicy bajtów.
Jak działa „autosynchronizacja” w UTF-8? Czy możesz podać przykłady 1-bajtowego i 2-bajtowego znaku?
Koray Tugay
2
@KorayTugay Prawidłowe łańcuchy krótszych bajtów nigdy nie są używane w dłuższych znakach. Na przykład ASCII jest w zakresie 0-127, co oznacza, że wszystkie znaki jednobajtowe mają postać 0xxxxxxxw formacie binarnym. Wszystkie dwubajtowe znaki zaczynają się 110xxxxxod drugiego bajtu 10xxxxxx. Powiedzmy, że pierwszy znak dwubajtowej postaci został utracony. Jak tylko zobaczysz 10xxxxxxbez poprzedzającego 110xxxxxx, możesz z całą pewnością stwierdzić, że bajt został utracony lub uszkodzony, i odrzucić ten znak (lub ponownie poprosić go z serwera lub cokolwiek innego) i przejść dalej, aż ponownie zobaczysz prawidłowy pierwszy bajt .
Chris
1
jeśli masz przesunięcie do znaku, masz przesunięcie do tego znaku - utf8, utf16 lub utf32 będą działały tak samo w tym przypadku; tzn. wszystkie są równie dobre w przypadkowym dostępie dzięki przesunięciu znaków do tablicy bajtów. Idea, że utf32 jest lepszy w liczeniu znaków niż utf8, jest również całkowicie fałszywa. Punkt kodowy (który nie jest tym samym znakiem, co znowu, nie jest taki sam jak grafem ... westchnienie), ma 32 bity szerokości w utf32 i od 8 do 32 bitów w utf8, ale znak może obejmować wiele punktów kodowych, które niszczy główną przewagę, którą ludzie twierdzą, że utf32 ma nad utf8.
Jaśniejsze
14
Przeprowadziłem kilka testów, aby porównać wydajność bazy danych między UTF-8 i UTF-16 w MySQL.
W UTF-32 wszystkie znaki są kodowane za pomocą 32 bitów. Zaletą jest to, że można łatwo obliczyć długość łańcucha. Wadą jest to, że dla każdego znaku ASCII tracisz dodatkowe trzy bajty.
W znakach UTF-8 zmienna długość, znaki ASCII są kodowane jednym bajtem (osiem bitów), większość zachodnich znaków specjalnych jest kodowana albo w dwóch bajtach, albo w trzech bajtach (na przykład € to trzy bajty), a bardziej egzotyczne znaki mogą zająć do czterech bajtów. Oczywistą wadą jest to, że a priori nie można obliczyć długości łańcucha. Ale kodowanie tekstu alfabetu łacińskiego (angielskiego) zajmuje o wiele mniej bajtów niż w przypadku UTF-32.
UTF-16 ma również zmienną długość. Znaki są kodowane albo w dwóch bajtach, albo w czterech bajtach. Naprawdę nie widzę sensu. Ma tę wadę, że ma zmienną długość, ale nie ma zalet oszczędzania tyle miejsca, co UTF-8.
Z tych trzech najwyraźniej najbardziej rozpowszechniony jest UTF-8.
Dlaczego miałbym chcieć obliczyć długość ciągu podczas tworzenia stron internetowych? Czy jest jakaś zaleta wyboru UTF-8 / UTF-16 w tworzeniu stron internetowych?
Morfidon
„Zaletą jest to, że możesz łatwo obliczyć długość łańcucha” Jeśli zdefiniujesz długość przez # współrzędnych kodowych, to tak, możesz po prostu podzielić długość bajtu przez 4, aby uzyskać go za pomocą UTF-32. Nie jest to jednak bardzo przydatna definicja: może nie odnosić się do liczby znaków. Również normalizacja może zmienić liczbę punktów kodowych w ciągu. Na przykład francuskie słowo „été” można zakodować na co najmniej 4 różne sposoby, przy użyciu 3 różnych długości punktów kodowych.
UTF-16 jest prawdopodobnie szybszy niż UTF-8, a jednocześnie nie marnuje pamięci jak UTF-32.
Michal Štein
6
W zależności od środowiska programistycznego możesz nie mieć nawet wyboru, jakiego kodowania typu danych łańcuchowych użyjesz wewnętrznie.
Ale do przechowywania i wymiany danych zawsze używałbym UTF-8, jeśli masz wybór. Jeśli masz głównie dane ASCII, da ci to najmniejszą ilość danych do przesłania, a jednocześnie będziesz w stanie zakodować wszystko. Optymalizacja pod kątem najmniejszej liczby operacji we / wy jest sposobem na zastosowanie nowoczesnych maszyn.
Prawdopodobnie o wiele ważniejszy niż wymagania przestrzenne jest fakt, że UTF-8 jest odporny na endianizm. UTF-16 i UTF-32 nieuchronnie będą musiały poradzić sobie z problemami endianizmu, gdzie UTF-8 jest po prostu strumieniem oktetów.
IInspectable
2
Jak wspomniano, różnica polega przede wszystkim na wielkości zmiennych podstawowych, które w każdym przypadku stają się większe, aby umożliwić reprezentację większej liczby znaków.
Jednak czcionki, kodowanie i inne rzeczy są wyjątkowo skomplikowane (niepotrzebnie?), Więc do wypełnienia bardziej szczegółowych informacji potrzebny jest duży link:
Nie oczekuj, że wszystko zrozumiesz, ale jeśli nie chcesz później problemów, warto dowiedzieć się jak najwięcej, tak wcześnie, jak to możliwe (lub po prostu zachęcić kogoś innego do rozwiązania tego problemu).
lub po prostu użyj UTF-8 jako domyślnego, ponieważ stał się on de facto standardem i dowiedz się, czy nowy system go obsługuje, czy nie. jeśli nie, możesz wrócić do tego postu.
robotik
-2
Krótko mówiąc, jedynym powodem użycia UTF-16 lub UTF-32 jest odpowiednio obsługa skryptów innych niż angielski i starożytnych.
Zastanawiałem się, dlaczego ktokolwiek zdecydowałby się na kodowanie inne niż UTF-8, skoro jest to oczywiście bardziej wydajne do celów internetowych / programistycznych.
Powszechne nieporozumienie - sufiksowana liczba NIE wskazuje na jej możliwości. Wszystkie obsługują pełny Unicode, tyle że UTF-8 może obsługiwać ASCII za pomocą jednego bajtu, więc jest WIĘCEJ wydajny / mniej uszkodzony dla procesora i przez Internet.
Nie jestem pewien, dlaczego sugerujesz, że używanie UTF-16 lub UTF-32 miało obsługiwać tekst w języku innym niż angielski. UTF-8 może sobie z tym poradzić. W tekście angielskim są też znaki spoza ASCII. Jak łącznik o zerowej szerokości. Lub kreska. Obawiam się, że ta odpowiedź nie wnosi dużej wartości.
IInspectable
To pytanie może zostać poddane głosowaniu w dół, ponieważ UTF-8 jest nadal powszechnie używany w plikach HTML, nawet jeśli większość znaków to 3-bajtowe znaki w UTF-8,
Ṃųỻịgǻňạcểơửṩ
@Inspectable support nie jest najlepszym sformułowaniem, promowanie lub lepsze wsparcie byłoby bardziej dokładne
robotik
Wysyłanie strony takiej jak utf8everywhere.org nie jest tym, co zrobiłbym w odpowiedzi SO.
Odpowiedzi:
UTF-8 ma tę zaletę, że znaki ASCII reprezentują większość znaków w bloku tekstu, ponieważ UTF-8 koduje je na 8 bitów (jak ASCII). Korzystne jest również to, że plik UTF-8 zawierający tylko znaki ASCII ma takie samo kodowanie jak plik ASCII.
UTF-16 jest lepszy tam, gdzie ASCII nie dominuje, ponieważ używa głównie 2 bajtów na znak. UTF-8 zacznie używać 3 lub więcej bajtów dla znaków wyższego rzędu, gdzie UTF-16 pozostaje na poziomie zaledwie 2 bajtów dla większości znaków.
UTF-32 obejmie wszystkie możliwe znaki w 4 bajtach. To sprawia, że jest dość wzdęty. Nie mogę wymyślić żadnej korzyści z jego używania.
źródło
W skrócie:
Długie: patrz Wikipedia: UTF-8 , UTF-16 i UTF-32 .
źródło
wchar_t
domyślnie ma 4 bajty. gcc ma opcję,-fshort-wchar
która zmniejsza rozmiar do 2 bajtów, ale psuje binarną kompatybilność ze standardowymi bibliotekami lib.UTF-8 ma zmienną liczbę od 1 do 4 bajtów.
UTF-16 ma zmienną 2 lub 4 bajty.
UTF-32 ma ustalone 4 bajty.
Uwaga: UTF-8 może zająć od 1 do 6 bajtów zgodnie z najnowszą konwencją: https://lists.gnu.org/archive/html/help-flex/2005-01/msg00030.html
źródło
Unicode definiuje pojedynczy ogromny zestaw znaków, przypisując jedną unikalną wartość całkowitą każdemu symbolowi graficznemu (jest to duże uproszczenie i tak naprawdę nie jest prawdą, ale jest wystarczająco blisko dla celów tego pytania). UTF-8/16/32 to po prostu różne sposoby kodowania tego.
W skrócie, UTF-32 używa 32-bitowych wartości dla każdego znaku. To pozwala im używać kodu o stałej szerokości dla każdego znaku.
UTF-16 domyślnie używa 16-bitów, ale daje to tylko 65 000 możliwych znaków, co jest dalekie od pełnego zestawu Unicode. Dlatego niektóre znaki używają par 16-bitowych wartości.
A UTF-8 domyślnie używa wartości 8-bitowych, co oznacza, że 127 pierwszych wartości są znakami jednobajtowymi o stałej szerokości (najbardziej znaczący bit służy do oznaczenia, że jest to początek sekwencji wielobajtowej, pozostawiając 7 bity dla rzeczywistej wartości znaku). Wszystkie pozostałe znaki są kodowane jako ciągi do 4 bajtów (jeśli pamięć służy).
To prowadzi nas do korzyści. Każda postać ASCII jest bezpośrednio kompatybilna z UTF-8, więc do aktualizacji starszych aplikacji, UTF-8 jest powszechnym i oczywistym wyborem. W prawie wszystkich przypadkach zużywa również najmniej pamięci. Z drugiej strony nie możesz dać żadnych gwarancji co do szerokości znaku. Może mieć szerokość 1, 2, 3 lub 4 znaków, co utrudnia manipulację łańcuchem.
UTF-32 jest przeciwny, zużywa najwięcej pamięci (każdy znak ma stałą szerokość 4 bajtów), ale z drugiej strony wiesz, że każda postać ma tę dokładną długość, więc manipulowanie ciągiem staje się znacznie prostsze. Możesz obliczyć liczbę znaków w ciągu po prostu na podstawie długości w bajtach ciągu. Nie możesz tego zrobić z UTF-8.
UTF-16 to kompromis. Pozwala większości znaków zmieścić się w 16-bitowej wartości o stałej szerokości. Tak długo, jak nie masz chińskich symboli, nut lub niektórych innych, możesz założyć, że każda postać ma szerokość 16 bitów. Zużywa mniej pamięci niż UTF-32. Ale jest pod pewnymi względami „najgorszy z obu światów”. Prawie zawsze zużywa więcej pamięci niż UTF-8, i nadal nie omija problemu, który nęka UTF-8 (znaki o zmiennej długości).
Wreszcie często pomocne jest po prostu skorzystanie z obsługi platformy. Windows używa UTF-16 wewnętrznie, więc w Windows jest to oczywisty wybór.
Linux różni się nieco, ale ogólnie używają UTF-8 do wszystkiego, co jest zgodne z Unicode.
Tak krótka odpowiedź: wszystkie trzy kodowania mogą kodować ten sam zestaw znaków, ale reprezentują każdy znak jako różne sekwencje bajtów.
źródło
Unicode jest standardem, a o UTF-x można pomyśleć jako techniczną implementację do niektórych praktycznych celów:
źródło
Próbowałem w prosty sposób wyjaśnić moje posty na blogu .
UTF-32
wymaga 32 bitów (4 bajty) do zakodowania dowolnego znaku. Na przykład, aby przedstawić kodowy punkt „A” za pomocą tego schematu, musisz wpisać 65 w 32-bitowej liczbie binarnej:
Jeśli przyjrzysz się bliżej, zauważysz, że najbardziej odpowiednie siedem bitów jest w rzeczywistości tymi samymi bitami, gdy używasz schematu ASCII. Ale ponieważ UTF-32 jest schematem o stałej szerokości , musimy dołączyć trzy dodatkowe bajty. Oznacza to, że jeśli mamy dwa pliki zawierające tylko znak „A”, jeden jest zakodowany w formacie ASCII, a drugi w formacie UTF-32, ich rozmiar będzie wynosił odpowiednio 1 bajt i 4 bajty.
UTF-16
Wiele osób uważa, że ponieważ UTF-32 używa stałej bitowej 32 do reprezentowania punktu kodowego, UTF-16 ma stałą szerokość 16 bitów. ŹLE!
W UTF-16 punkt kodowy może być reprezentowany albo w 16 bitach, albo w 32 bitach. Ten schemat to system kodowania o zmiennej długości. Jaka jest przewaga nad UTF-32? Przynajmniej w przypadku ASCII rozmiar plików nie będzie 4-krotnie większy niż oryginał (ale nadal dwa razy), więc nadal nie jesteśmy kompatybilni wstecznie ASCII.
Ponieważ 7 bitów wystarcza do przedstawienia znaku „A”, możemy teraz używać 2 bajtów zamiast 4, takich jak UTF-32. Będzie to wyglądać jak:
UTF-8
Zgadłeś słusznie. W UTF-8 punkt kodowy może być reprezentowany przy użyciu 32, 16, 24 lub 8 bitów, a jako system UTF-16 jest to także system kodowania o zmiennej długości.
Wreszcie możemy przedstawić „A” w taki sam sposób, w jaki reprezentujemy go za pomocą systemu kodowania ASCII:
Mały przykład, w którym UTF-16 jest rzeczywiście lepszy niż UTF-8:
Rozważmy chińską literę „語” - jej kodowanie UTF-8 to:
Chociaż jego kodowanie UTF-16 jest krótsze:
Aby zrozumieć reprezentację i jej interpretację, odwiedź oryginalny post.
źródło
UTF-8
UTF-16
UTF-32
UTF-8 będzie najbardziej efektywny pod względem miejsca, chyba że większość znaków pochodzi z przestrzeni znaków CJK (chińskiej, japońskiej i koreańskiej).
UTF-32 najlepiej nadaje się do losowego dostępu poprzez przesunięcie znaków w tablicy bajtów.
źródło
0xxxxxxx
w formacie binarnym. Wszystkie dwubajtowe znaki zaczynają się110xxxxx
od drugiego bajtu10xxxxxx
. Powiedzmy, że pierwszy znak dwubajtowej postaci został utracony. Jak tylko zobaczysz10xxxxxx
bez poprzedzającego110xxxxxx
, możesz z całą pewnością stwierdzić, że bajt został utracony lub uszkodzony, i odrzucić ten znak (lub ponownie poprosić go z serwera lub cokolwiek innego) i przejść dalej, aż ponownie zobaczysz prawidłowy pierwszy bajt .Przeprowadziłem kilka testów, aby porównać wydajność bazy danych między UTF-8 i UTF-16 w MySQL.
Aktualizuj prędkości
UTF-8
UTF-16
Wstaw prędkości
Usuń prędkości
źródło
W UTF-32 wszystkie znaki są kodowane za pomocą 32 bitów. Zaletą jest to, że można łatwo obliczyć długość łańcucha. Wadą jest to, że dla każdego znaku ASCII tracisz dodatkowe trzy bajty.
W znakach UTF-8 zmienna długość, znaki ASCII są kodowane jednym bajtem (osiem bitów), większość zachodnich znaków specjalnych jest kodowana albo w dwóch bajtach, albo w trzech bajtach (na przykład € to trzy bajty), a bardziej egzotyczne znaki mogą zająć do czterech bajtów. Oczywistą wadą jest to, że a priori nie można obliczyć długości łańcucha. Ale kodowanie tekstu alfabetu łacińskiego (angielskiego) zajmuje o wiele mniej bajtów niż w przypadku UTF-32.
UTF-16 ma również zmienną długość. Znaki są kodowane albo w dwóch bajtach, albo w czterech bajtach. Naprawdę nie widzę sensu. Ma tę wadę, że ma zmienną długość, ale nie ma zalet oszczędzania tyle miejsca, co UTF-8.
Z tych trzech najwyraźniej najbardziej rozpowszechniony jest UTF-8.
źródło
W zależności od środowiska programistycznego możesz nie mieć nawet wyboru, jakiego kodowania typu danych łańcuchowych użyjesz wewnętrznie.
Ale do przechowywania i wymiany danych zawsze używałbym UTF-8, jeśli masz wybór. Jeśli masz głównie dane ASCII, da ci to najmniejszą ilość danych do przesłania, a jednocześnie będziesz w stanie zakodować wszystko. Optymalizacja pod kątem najmniejszej liczby operacji we / wy jest sposobem na zastosowanie nowoczesnych maszyn.
źródło
Jak wspomniano, różnica polega przede wszystkim na wielkości zmiennych podstawowych, które w każdym przypadku stają się większe, aby umożliwić reprezentację większej liczby znaków.
Jednak czcionki, kodowanie i inne rzeczy są wyjątkowo skomplikowane (niepotrzebnie?), Więc do wypełnienia bardziej szczegółowych informacji potrzebny jest duży link:
http://www.cs.tut.fi/~jkorpela/chars.html#ascii
Nie oczekuj, że wszystko zrozumiesz, ale jeśli nie chcesz później problemów, warto dowiedzieć się jak najwięcej, tak wcześnie, jak to możliwe (lub po prostu zachęcić kogoś innego do rozwiązania tego problemu).
Paweł.
źródło
Krótko mówiąc, jedynym powodem użycia UTF-16 lub UTF-32 jest odpowiednio obsługa skryptów innych niż angielski i starożytnych.
Zastanawiałem się, dlaczego ktokolwiek zdecydowałby się na kodowanie inne niż UTF-8, skoro jest to oczywiście bardziej wydajne do celów internetowych / programistycznych.
Powszechne nieporozumienie - sufiksowana liczba NIE wskazuje na jej możliwości. Wszystkie obsługują pełny Unicode, tyle że UTF-8 może obsługiwać ASCII za pomocą jednego bajtu, więc jest WIĘCEJ wydajny / mniej uszkodzony dla procesora i przez Internet.
Dobra lektura: http://www.personal.psu.edu/ejp10/blogs/gotunicode/2007/10/which_utf_do_i_use.html i http://utf8everywhere.org
źródło