Jaka jest podstawa Unicode i dlaczego potrzeba UTF-8 lub UTF-16? Sprawdziłem to w Google i szukałem tutaj, ale nie jest to dla mnie jasne.
W VSS podczas porównywania plików czasami pojawia się komunikat informujący, że oba pliki mają różne UTF. Dlaczego miałoby tak być?
Proszę wyjaśnić w prosty sposób.
Odpowiedzi:
Dlaczego potrzebujemy Unicode?
W (niezbyt) pierwszych dniach istniało tylko ASCII. To było w porządku, ponieważ wszystko, co kiedykolwiek będzie potrzebne, to kilka znaków kontrolnych, interpunkcja, cyfry i litery, takie jak te w tym zdaniu. Niestety, dzisiejszy dziwny świat globalnej komunikacji i mediów społecznościowych nie został przewidziany i nie jest niczym niezwykłym, aby zobaczyć angielski, العربية, 汉语, עִבְרִית, ελληνικά i ភាសាខ្មែរ w tym samym dokumencie (mam nadzieję, że nie złamałem żadnego starego przeglądarki).
Ale dla argumentu powiedzmy, że Joe Average jest programistą. Podkreśla, że zawsze będzie potrzebował tylko angielskiego i jako taki chce tylko używać ASCII. Może to być w porządku dla użytkownika Joe , ale nie jest to w porządku dla Joe , twórcy oprogramowania . Około połowa świata używa znaków innych niż łacińskie, a używanie ASCII jest prawdopodobnie bez znaczenia dla tych ludzi, a ponadto zamyka swoje oprogramowanie na dużą i rozwijającą się gospodarkę.
Dlatego potrzebny jest zestaw znaków obejmujący wszystkie języki. Tak powstał Unicode. Przypisuje każdemu znakowi unikalny numer zwany punktem kodowym . Jedną zaletą Unicode w porównaniu z innymi możliwymi zestawami jest to, że pierwsze 256 punktów kodowych jest identycznych z ISO-8859-1 , a zatem także ASCII. Ponadto zdecydowana większość powszechnie używanych znaków jest reprezentowana tylko przez dwa bajty w regionie zwanym podstawową płaszczyzną wielojęzyczną (BMP) . Teraz potrzebne jest kodowanie znaków, aby uzyskać dostęp do tego zestawu znaków, a jak zadaje pytanie, skoncentruję się na UTF-8 i UTF-16.
Uwagi dotyczące pamięci
Ile bajtów daje dostęp do znaków w tych kodowaniach?
Warto teraz wspomnieć, że do znaków spoza BMP należą starożytne skrypty, symbole matematyczne, symbole muzyczne oraz rzadsze znaki chińskie / japońskie / koreańskie (CJK) .
Jeśli będziesz pracował głównie ze znakami ASCII, to UTF-8 z pewnością jest bardziej wydajny pod względem pamięci. Jeśli jednak pracujesz głównie ze skryptami pozaeuropejskimi, użycie UTF-8 może być nawet 1,5 razy mniej wydajne niż UTF-16. W przypadku dużych ilości tekstu, takich jak duże strony internetowe lub długie dokumenty tekstowe, może to mieć wpływ na wydajność.
Podstawy kodowania
Uwaga: jeśli wiesz, jak są kodowane UTF-8 i UTF-16, przejdź do następnej sekcji, aby uzyskać praktyczne zastosowania.
1
uniknięcie kolizji ze znakami ASCII.Jak widać, UTF-8 i UTF-16 nie są ze sobą prawie kompatybilne. Więc jeśli wykonujesz operacje we / wy, upewnij się, że wiesz, jakiego kodowania używasz! Więcej informacji na temat tych kodowań można znaleźć w FAQ UTF .
Praktyczne uwagi dotyczące programowania
Typy znaków i ciągów znaków: Jak są one kodowane w języku programowania? Jeśli są to nieprzetworzone bajty, w momencie, gdy spróbujesz wyprowadzić znaki inne niż ASCII, możesz napotkać kilka problemów. Ponadto, nawet jeśli typ znaku jest oparty na UTF, nie oznacza to, że łańcuchy są poprawne UTF. Mogą zezwalać na sekwencje bajtów, które są nielegalne. Ogólnie rzecz biorąc, będziesz musiał użyć biblioteki obsługującej UTF, takiej jak ICU dla C, C ++ i Java. W każdym razie, jeśli chcesz wprowadzić / wyprowadzić coś innego niż domyślne kodowanie, najpierw musisz je przekonwertować.
Zalecane / domyślne / dominujące kodowanie: Gdy ma się wybór, którego UTF ma używać, zwykle najlepiej jest przestrzegać zalecanych standardów dla środowiska, w którym pracujesz. Na przykład UTF-8 dominuje w Internecie, a od HTML5 to jest zalecanym kodowaniem . I odwrotnie, zarówno środowiska .NET, jak i Java są oparte na typie znaków UTF-16. Myląco (i niepoprawnie) często pojawiają się odwołania do „kodowania Unicode”, które zwykle odnosi się do dominującego kodowania UTF w danym środowisku.
Obsługa bibliotek: używane biblioteki obsługują pewnego rodzaju kodowanie. Który? Czy obsługują skrzynki narożne? Ponieważ konieczność jest matką wynalazku, biblioteki UTF-8 będą na ogół poprawnie obsługiwały znaki 4-bajtowe, ponieważ 1, 2, a nawet 3 bajty mogą występować często. Jednak nie wszystkie rzekome biblioteki UTF-16 prawidłowo obsługują pary zastępcze, ponieważ występują one bardzo rzadko.
Liczenie znaków: Istnieje łączenie znaków w Unicode. Na przykład punkt kodowy U + 006E (n) i U + 0303 (łącząca tylda) tworzy ñ, ale punkt kodowy U + 00F1 tworzy ñ. Powinny wyglądać identycznie, ale prosty algorytm zliczania zwróci 2 dla pierwszego przykładu, 1 dla drugiego. To niekoniecznie jest złe, ale może nie być pożądanym rezultatem.
Porównywanie pod względem równości: A, А i Α wyglądają tak samo, ale są to odpowiednio: łaciński, cyrylica i grecki. Masz również przypadki takie jak C i Ⅽ, jedna to litera, a druga cyfra rzymska. Ponadto mamy również do rozważenia łączące postacie. Aby uzyskać więcej informacji, zobacz Zduplikowane znaki w Unicode .
Pary zastępcze: pojawiają się dość często na SO, więc podam tylko kilka przykładowych linków:
Inni ?:
źródło
źródło
Ponieważ zawsze potrzebny jest wiarygodny zasób, ale oficjalny raport jest ogromny, proponuję przeczytać:
Krótkie wyjaśnienie:
Komputery czytają bajty, a ludzie czytają znaki, dlatego używamy standardów kodowania do mapowania znaków na bajty. ASCII był pierwszym powszechnie stosowanym standardem, ale obejmuje tylko łacinę (7 bitów / znak może reprezentować 128 różnych znaków). Unicode jest standardem, którego celem jest objęcie wszystkich możliwych znaków na świecie (może pomieścić do 1 114 112 znaków, co oznacza maksymalnie 21 bitów / znak. Obecny Unicode 8.0 określa łącznie 120 737 znaków, i to wszystko).
Główna różnica polega na tym, że znak ASCII może pasować do bajtu (8 bitów), ale większość znaków Unicode nie. Tak więc stosuje się kodowanie formularzy / schematów (takich jak UTF-8 i UTF-16), a model znaków wygląda następująco:
Każdy znak zajmuje wyliczoną pozycję od 0 do 1 114 111 (hex: 0-10FFFF) zwaną punktem kodowym .
Formularz kodowania odwzorowuje punkt kodowy na sekwencję jednostek kodowych. Jednostka kodowa to sposób, w jaki znaki mają być zorganizowane w pamięci, jednostki 8-bitowe, jednostki 16-bitowe i tak dalej. UTF-8 wykorzystuje 1 do 4 jednostek 8 bitów, a UTF-16 wykorzystuje 1 lub 2 jednostki 16 bitów, aby pokryć cały Unicode o maksymalnej długości 21 bitów. Jednostki używają prefiksów, aby można było dostrzec granice znaków, a więcej jednostek oznacza więcej prefiksów, które zajmują bity. Tak więc, chociaż UTF-8 używa 1 bajtu dla skryptu łacińskiego, potrzebuje 3 bajtów dla późniejszych skryptów w Basic Multilingual Plane, podczas gdy UTF-16 używa 2 bajtów dla wszystkich tych. I to jest ich główna różnica.
Wreszcie schemat kodowania (jak UTF-16BE lub UTF-16LE) odwzorowuje (serializuje) sekwencję jednostek kodu na sekwencję bajtów.
znak: π
punkt kodowy:
formularze kodowania U + 03C0 (jednostki kodowe):
UTF-8: CF 80
Schematy
kodowania UTF-16: 03C0 (bajty):
UTF-8: CF 80
UTF-16BE: 03 C0
UTF-16LE: C0 03
Wskazówka: cyfra szesnastkowa reprezentuje 4 bity, więc dwucyfrowa liczba szesnastkowa reprezentuje bajt
Spójrz również na mapy samolotów w Wikipedii, aby poznać układ zestawu znaków
źródło
Początkowo Unicode miał mieć 16-bitowe kodowanie o stałej szerokości (UCS-2). Pierwsi użytkownicy Unicode, tacy jak Java i Windows NT, budowali swoje biblioteki wokół 16-bitowych ciągów.
Później zakres Unicode został rozszerzony o znaki historyczne, które wymagałyby więcej niż 65 536 punktów kodowych obsługiwanych przez kodowanie 16-bitowe. Aby umożliwić reprezentowanie dodatkowych znaków na platformach, które korzystały z UCS-2, wprowadzono kodowanie UTF-16. Używa „par zastępczych” do reprezentowania postaci w dodatkowych płaszczyznach.
Tymczasem wiele starszych programów i protokołów sieciowych używało 8-bitowych ciągów. UTF-8 został stworzony, aby systemy te mogły obsługiwać Unicode bez konieczności używania szerokich znaków. Jest kompatybilny wstecz z 7-bitowym ASCII.
źródło
W tym artykule wyjaśniono wszystkie szczegóły http://kunststube.net/encoding/
PISANIE DO BUFORA
jeśli napiszesz do 4-bajtowego bufora, symbolu
あ
z kodowaniem UTF8, twój plik binarny będzie wyglądał następująco:00000000 11100011 10000001 10000010
jeśli napiszesz do 4-bajtowego bufora, symbolu
あ
z kodowaniem UTF16, twój plik binarny będzie wyglądał następująco:00000000 00000000 00110000 01000010
Jak widać, w zależności od tego, jakiego języka użyjesz w swoich treściach, wpłynie to odpowiednio na twoją pamięć.
np. dla tego konkretnego symbolu:
あ
kodowanie UTF16 jest bardziej wydajne, ponieważ mamy 2 zapasowe bajty do wykorzystania dla następnego symbolu. Ale to nie znaczy, że musisz używać UTF16 dla japońskiego alfabetu.CZYTANIE Z BUFORA
Teraz, jeśli chcesz przeczytać powyższe bajty, musisz wiedzieć, w jakim kodowaniu zostało zapisane, i poprawnie je odkodować.
np. jeśli zdekodujesz to: 00000000 11100011 10000001 10000010 do kodowania UTF16, skończysz na
臣
nieあ
Uwaga: Kodowanie i Unicode to dwie różne rzeczy. Unicode to duży (tabela) z każdym symbolem odwzorowanym na unikalny punkt kodowy. np.
あ
symbol (litera) ma (punkt kodowy) : 30 42 (szesnastkowy). Z drugiej strony kodowanie jest algorytmem, który konwertuje symbole na bardziej odpowiedni sposób, gdy są przechowywane na sprzęcie.źródło
Unicode jest standardem, który odwzorowuje znaki we wszystkich językach na określoną wartość liczbową o nazwie Punkty kodowe . Powodem tego jest to, że umożliwia różne kodowania przy użyciu tego samego zestawu punktów kodowych.
UTF-8 i UTF-16 to dwa takie kodowania. Biorą punkty kodowe jako dane wejściowe i kodują je przy użyciu dobrze zdefiniowanej formuły w celu wytworzenia zakodowanego ciągu.
Wybór konkretnego kodowania zależy od twoich wymagań. Różne kodowania mają różne wymagania dotyczące pamięci i w zależności od znaków, z którymi będziesz mieć do czynienia, powinieneś wybrać kodowanie, które używa najmniejszej sekwencji bajtów do kodowania tych znaków.
Więcej szczegółowych informacji na temat Unicode, UTF-8 i UTF-16 można znaleźć w tym artykule,
Co każdy programista powinien wiedzieć o Unicode
źródło
Dlaczego Unicode? Ponieważ ASCII ma tylko 127 znaków. Te od 128 do 255 różnią się w różnych krajach, dlatego istnieją strony kodowe. Więc powiedzieli, że możemy mieć do 1114111 znaków. Jak więc przechowywać najwyższy punkt kodowy? Musisz go zapisać przy użyciu 21 bitów, więc użyjesz DWORDa zawierającego 32 bity i 11 bitów zmarnowanych. Jeśli więc używasz DWORD do przechowywania znaku Unicode, jest to najłatwiejszy sposób, ponieważ wartość w DWORD jest dokładnie zgodna z punktem kodowym. Ale tablice DWORD są oczywiście większe niż tablice WORD i oczywiście nawet większe niż tablice BYTE. Dlatego istnieje nie tylko utf-32, ale także utf-16. Ale utf-16 oznacza strumień WORD, a WORD ma 16 bitów, więc jak najwyższy punkt kodowy 1114111 pasuje do WORD? Nie może! Więc umieszczają wszystko powyżej 65535 w DWORD, który nazywają parą zastępczą. Taką parą zastępczą są dwa SŁOWA i można je wykryć, patrząc na pierwsze 6 bitów. A co z utf-8? Jest to tablica bajtów lub strumień bajtów, ale w jaki sposób najwyższy punkt kodowy 1114111 może się zmieścić w bajcie? Nie może! Okej, więc wstawili również DWORD, prawda? A może SŁOWO, prawda? Prawie dobrze! Wynaleźli sekwencje utf-8, co oznacza, że każdy punkt kodowy wyższy niż 127 musi zostać zakodowany w sekwencji 2-bajtowej, 3-bajtowej lub 4-bajtowej. Łał! Ale jak możemy wykryć takie sekwencje? Cóż, wszystko do 127 to ASCII i jeden bajt. To, co zaczyna się od 110, to sekwencja dwubajtowa, to, co zaczyna się od 1110, to trzy bajtowa sekwencja, a to, co zaczyna się od 11110, to czterobajtowa sekwencja. Pozostałe bity tych tak zwanych „startbytes” należą do punktu kodowego. Teraz w zależności od sekwencji muszą następować następujące bajty. Kolejny bajt zaczyna się od 10, pozostałe bity to 6 bitów bitów danych i należą do punktu kodowego. Połącz bity ładunku startbyte i następujących bajtów / s, a otrzymasz kodowy punkt. To cała magia utf-8.
źródło
ASCII - Oprogramowanie przydziela tylko 8 bajtów w pamięci dla danego znaku. Działa dobrze dla znaków angielskich i przyjętych (słowa pożyczkowe, takie jak fasada), ponieważ odpowiadające im wartości dziesiętne spadają poniżej 128 w wartości dziesiętnej. Przykładowy program C.
UTF-8 - Oprogramowanie przydziela 1 do 4 zmiennych 8-bitowych bajtów dla danego znaku. Co oznacza tutaj zmienna? Powiedzmy, że wysyłasz znak „A” przez strony HTML w przeglądarce (HTML to UTF-8), odpowiadająca mu wartość dziesiętna A wynosi 65, a po konwersji na dziesiętną staje się ona 01000010. Wymaga to tylko 1 bajtu , 1 bajt pamięci jest przydzielany nawet dla specjalnie przyjętych angielskich znaków, takich jak „ç” na fasadzie wyrazu. Jednak jeśli chcesz przechowywać znaki europejskie, wymaga 2 bajtów, więc potrzebujesz UTF-8. Jeśli jednak wybierasz znaki azjatyckie, potrzebujesz minimum 2 bajtów i maksymalnie 4 bajtów. Podobnie, emoji wymagają 3 do 4 bajtów. UTF-8 zaspokoi wszystkie Twoje potrzeby.
UTF-16 przydzieli minimum 2 bajty i maksymalnie 4 bajty na znak, nie przydzieli 1 lub 3 bajtów. Każdy znak jest reprezentowany w postaci 16 lub 32 bitów.
Dlaczego więc istnieje UTF-16? Początkowo Unicode był 16-bitowy, a nie 8-bitowy. Java przyjęła oryginalną wersję UTF-16.
W skrócie, nie potrzebujesz nigdzie UTF-16, chyba że został już przyjęty przez język lub platformę, nad którą pracujesz.
Program Java wywoływany przez przeglądarki internetowe używa UTF-16, ale przeglądarka internetowa wysyła znaki za pomocą UTF-8.
źródło
UTF oznacza skrót od Unicode Transformation Format. Zasadniczo w dzisiejszym świecie istnieją skrypty napisane w setkach innych języków, formatach nieobjętych wcześniej używanym podstawowym ASCII. Stąd powstała UTF.
UTF-8 ma możliwości kodowania znaków, a jego jednostka kodowa to 8 bitów, natomiast w przypadku UTF-16 jest to 16 bitów.
źródło