Dlaczego istnieje wiele kodowań Unicode?

41

Myślałem, że Unicode został zaprojektowany, aby obejść cały problem posiadania wielu różnych kodowań z powodu małej przestrzeni adresowej (8 bitów) w większości wcześniejszych prób (ASCII itp.).

Dlaczego więc jest tyle kodowań Unicode? Nawet wiele wersji (zasadniczo) tej samej, takich jak UTF-8, UTF-16 itp.

Matthew Scharley
źródło
11
UTF-8 to nie to samo co UTF-16. Lista będzie rosła, gdy tylko napotkamy inne układy słoneczne z planetami podobnymi do Ziemi.
setzamora
1
@Joset: Mamy już Klingona. Mamy większość języków ziemi na BMP z niewielkim rozlaniem na równiny 1,2. Jeśli obecne teorie są poprawne i istnieje tylko 42 czujące gatunki w galaktyce, które osiągają punkt, w którym mogą korzystać z podróży kosmicznych (umożliwiając w ten sposób pierwszy kontakt), powinniśmy być w stanie wycisnąć wszystkie postacie we wszystkich językach do UNICODE (zakładając, że możemy rozwinąć od 21 do 22 bitów, aby umożliwić 64 równin). To nawet pozostawia 10 bitów przestrzeni buforowej, jeśli chcemy uwzględnić prymitywne gatunki, które nie osiągnęły lotu kosmicznego.
Martin York,
7
@Kevin Hsu: UTF-7,8,16LE, 16BE, 32LE, 32BE. Zatem istnieje co najmniej 6 prawdziwych kodowań. UTF-9 i UTF-18 to prima aprilis.
MSalters
9
Zaletą
1
Zobacz, co Spolsky miał do powiedzenia na temat Unicode i kodowania .
MPelletier,

Odpowiedzi:

29

Ponieważ ludzie nie chcą wydawać 21 bitów na każdą postać. We wszystkich nowoczesnych systemach oznaczałoby to w zasadzie użycie trzech bajtów na znak, czyli trzy razy więcej niż ludzie przyzwyczaili się, więc w ogóle nie chcieli używać Unicode. Trzeba było znaleźć kompromisy: np. UTF-8 świetnie nadaje się do tekstu w języku angielskim, ponieważ starsze pliki ASCII wcale nie muszą być konwertowane, ale są mniej przydatne w językach europejskich i mało przydatne w językach azjatyckich.

Zasadniczo tak, moglibyśmy zdefiniować jedno uniwersalne kodowanie, a także jedną uniwersalną tabelę znaków, ale rynek nie zaakceptowałby tego.

Kilian Foth
źródło
8
+1 Świetna odpowiedź. Szczerze mówiąc, to jedyna osoba, która naprawdę odpowiada na to pytanie. Wszystkie pozostałe odpowiedzi dotyczą (mniej więcej) tego, w jaki sposób bajty są rozmieszczone we wszystkich różnych kodowaniach Unicode.
Jacek Prucia
Historycznie jest to prosta kwestia braku porozumienia. Jednak nie widzę dziś większego zastosowania do niczego poza UTF-8, chociaż istnieją teoretyczne scenariusze, w których UTF-16 zajmowałby mniej miejsca, nie jest to duża różnica i są rzadkie. Najbardziej znanym miejscem, w którym chciałbyś zaoszczędzić miejsce, są strony internetowe, ale są one pełne kodów HTML, które są najkrótsze przy użyciu UTF-8. Możesz na przykład użyć, Shift JISaby zmniejszyć japońską stronę internetową niż odpowiednik UTF-8, ale to działa tylko dlatego, że jest to zestaw znaków specjalnie dla japońskiego.
aaaaaaaaaaaa
2
To też nie do końca prawda. Ponieważ skompresowane formaty są używane tylko do transportu i przechowywania. W aplikacji częściej stosuje się UCS-2 lub UCS-4, ponieważ mają one stałą szerokość, ale zajmują 2 lub 4 bajty na znak. Dlatego aplikacje chętnie rezygnują z miejsca dla łatwości użytkowania.
Martin York
but it is less useful for European languages, and of little use for Asian languages- to po prostu źle. Przez „użyteczność” rozumiesz kompresję? Otóż ​​UTF-8 zapewnia lepszą kompresję dla języków europejskich, ponieważ w każdym tekście są spacje i znaki interpunkcyjne, które zajmują tylko jeden bajt.
Nick Volynkin
37

Unicode to 21-bitowy znak, który jednoznacznie opisuje „CodePoints”, każdy punkt kodowy jest reprezentowany przez glif (reprezentacja graficzna).

  • 16 bitów używanych do identyfikacji punktu kodowego na płaszczyźnie (większość punktów kodowych znajduje się na płaszczyźnie 0).
  • 5 bitów do identyfikacji samolotu.

Obsługiwane kodowania to:

  • UTF-8 (do kodowania każdego punktu za pomocą wartości 8-bitowych)
  • UTF-16 (do kodowania każdego punktu za pomocą 16-bitowych wartości)
  • UTF-32 (do kodowania każdego punktu za pomocą wartości 32-bitowych)

Ale bez względu na to, jakie kodowanie ma miejsce podczas dekodowania, wszystkie są mapowane z powrotem do określonego punktu kodowego, który ma to samo znaczenie (dlatego jest fajny).

UTF-8

Jest to format o zmiennej wielkości. Gdzie każdy punkt kodowy jest reprezentowany przez 1 do 4 bajtów.

UTF-16

Jest to format o zmiennej wielkości. Punkty kodowe na „podstawowej płaszczyźnie wielojęzycznej” (BMP lub płaszczyźnie 0) można przedstawić za pomocą 1 pojedynczej 16-bitowej wartości. Punkty kodowe na innych płaszczyznach są reprezentowane przez parę zastępczą (2 16-bitowe wartości).

UTF-32

Jest to format o stałym rozmiarze. Wszystkie punkty kodowe są reprezentowane przez pojedynczą 32-bitową wartość.

Martin York
źródło
2
Podoba mi się również ta odpowiedź. Pisałem jeden podobny, ale ten jest jasny. Dodałbym również, że UTF-8 jest również przydatny, ponieważ ciągi ASCII są automatycznie UTF-8.
Kevin Hsu,
4
Proszę, to Podstawowy wielojęzyczny samolot , a nie zwykły .
JSB
3
To dobra odpowiedź, ale myślę, że wciąż nasuwa się pytanie „Dlaczego?”, Chociaż odpowiedź ta w sposób dorozumiany dotyczy tego. Aby rozwinąć: UTF-32 jest bardziej bezpośrednim (niektórzy powiedzieliby, łatwiej) podejściem do kodowania znaków Unicode, ale marnuje również dużo miejsca, ponieważ każdy znak zajmuje 4 bajty. UTF-8 jest znacznie bardziej kompaktowy i kompatybilny wstecz z ASCII, ale nie jest regularny: znak może zabrać od 1 do 4 bajtów do zakodowania, co utrudnia pracę. UTF-16 jest rodzajem hybrydowego podejścia między nimi, głównie z zaletami i wadami każdego z nich.
mipadi
4
Istnieje kompromis między zużyciem pamięci (gdzie UTF-8 jest najlepszy, ponieważ najbardziej popularne znaki to jednobajty) a szybkością przetwarzania (gdzie UTF-32 jest najlepszy, ponieważ wszystkie znaki są tego samego rozmiaru, co pozwala na pewne optymalizacje i daje idealne 32-bitowe wyrównanie w pamięci). W rezultacie protokoły sieciowe i formaty plików zwykle używają UTF-8 (w celu zaoszczędzenia przepustowości / miejsca do przechowywania), podczas gdy tłumacze skryptów i środowiska wykonawcze języków mogą preferować UTF-16 lub UTF-32.
tdammers
2
@Marcel: „CodePoint” to „CodePoint”, a nie character(ponieważ znak może być zbudowany z wielu „CodePoints”). Nie myl dwóch terminów. Ale masz rację, „CodePoints” nie odnoszą się do glifów. Glif jest tylko graficzną reprezentacją punktu kodowego. Subtelna, ale ważna różnica.
Martin York,
25

Myślę, że warto rozdzielić 2 pomysły:

  1. Unicode - mapowanie znaków z całego świata na punkty kodowe.
  2. Kodowanie - mapowanie punktów kodowych na wzorce bitowe (UTF-8, UTF-16 itp.).

UTF-8, UTF-16 i inne kodowania mają swoje zalety i wady. Lepiej skonsultuj o tym Wikipedię .

jfs
źródło
@jfs: Dlaczego w ogóle ma Unicode, jeśli nadal będzie tuzin lub więcej różnych kodowań, które i tak są różne w kablu? Jakie zastosowanie ma samo w sobie mapowanie globalne?
Matthew Scharley,
10
@Matthew Scharley: Źle na to patrzysz. UNICODE mapuje wszystkie znaki ze wszystkich języków (w tym Klingon) na UNIQUE ID ( punkt kodowy). Kodowania są jedynie sposobem kompresji punktów kodowych na dysku lub strumieniu w sieci. UTF oznacza „UNICODE Transport format”. Zawsze powinieneś myśleć o punkcie kodowym UNICODE jako o wartości 21 bitów. Przewagą nad innymi formatami jest to, że wszystkie znaki są jednoznacznie identyfikowane i nie nakładają się (w przeciwieństwie do Latin-1, Latin-2 itp.).
Martin York
@Matthew Scharley Dlaczego globalne mapowanie? Właściwie każdy miał swoje własne mapowanie w przeszłości (pamiętasz strony kodowe?). Myślę, że głupi przykład rozwiąże sprawę. Wyobraź sobie ideę miłości. Jak będziesz to komuś reprezentował? Daj kwiaty? Powiedz kocham Cię"? Każdy ma swój sposób na wyrażenie tego. Miłość (która jest abstrakcyjnym pomysłem) przypomina punkty kodowe. Wyrażenie tego jest jak kodowanie. :)
jfs
4
Unicode to globalny alfabet. UTF-x jest sposobem, w jaki jest transportowany przez komputery, ponieważ trudno jest przepchnąć papier przez druty.
Mel
1
@Martin, Klingon faktycznie tego nie zrobił. Tengwar i Cirith nie używali też do pisania elfich języków Tolkeina.
TRiG
9

UTF-7, UTF-8, UTF-16 i UTF-32 są po prostu algorytmami formatów transformacji tego samego kodowania (punktów kodowych ) znaków. Są kodowaniem jednego systemu kodyfikacji znaków.

Są one również algorytmicznie łatwiejsze w nawigacji do przodu i do tyłu niż większość poprzednich schematów do obsługi zestawów znaków większych niż 256 znaków.

Jest to bardzo odmienne niż ogólnie kodyfikacja glifów w zależności od kraju, a czasem i dostawcy. W samej Japonii istniało mnóstwo odmian samego JIS, nie wspominając już o EUC-JP i transformacji JIS zorientowanej na stronę kodową, z której korzystały maszyny DOS / Windows o nazwie Shift-JIS. (Do pewnego stopnia miały miejsce ich algorytmiczne przekształcenia, ale nie były one szczególnie proste i występowały różnice w znakach specyficzne dla dostawcy. Pomnóż to przez kilkaset krajów i stopniową ewolucję bardziej wyrafinowanych systemów czcionek (po ekranie zieleni) era), a ty miałeś prawdziwy koszmar.

Po co ci te formy transformacji Unicode? Ponieważ wiele starszych systemów zakładało sekwencje 7-bitowych znaków ASCII, więc potrzebne było 7-bitowe czyste rozwiązanie bezpiecznie przepuszczające dane bez zakłóceń przez te systemy, więc potrzebny był UTF-7. Potem były bardziej nowoczesne systemy, które mogły radzić sobie z 8-bitowymi zestawami znaków, ale wartości null miały dla nich specjalne znaczenie, więc UTF-16 nie działał dla nich. 2 bajty mogłyby zakodować całą podstawową wielojęzyczną płaszczyznę Unicode w swoim pierwszym wcieleniu, więc UCS-2 wydawał się rozsądnym podejściem do systemów, które od samego początku będą „rozpoznawały Unicode” (jak Windows NT i Java VM); potem rozszerzenia poza tym wymagały dodatkowych znaków, co spowodowało algorytmiczną transformację kodowań o wartości 21 bitów zarezerwowanych przez standard Unicode i powstały pary zastępcze; wymagało to UTF-16. Jeśli miałeś jakieś zastosowanie, w którym spójność szerokości znaków była ważniejsza niż wydajność pamięci, opcja UTF-32 (kiedyś nazywana UCS-4) była opcją.

UTF-16 jest jedyną rzeczą, z którą zdalnie trudno sobie poradzić, i którą łatwo złagodzić niewielki zakres znaków, na który wpływa ta transformacja, oraz fakt, że wiodące 16-bitowe sekwencje znajdują się w całkowicie innym zakresie niż końcowy 16-bitowe sekwencje. To także światy łatwiejsze niż przesuwanie się do przodu i do tyłu w wielu kodowaniach wczesnoazjatyckich, gdzie albo potrzebowałeś maszyny państwowej (JIS i EUC), aby poradzić sobie z sekwencjami ucieczki, lub potencjalnie cofnąłeś kilka postaci, aż znajdziesz coś, co było gwarantowane być tylko wiodącym bajtem (Shift-JIS). UTF-16 miał również pewne zalety w systemach, które potrafiłyby również wydajnie przeszukiwać 16-bitowe sekwencje.

Chyba że musiałeś przeżyć dziesiątki (setki, naprawdę) różnych kodowań lub zbudować systemy obsługujące wiele języków w różnych kodowaniach, czasem nawet w tym samym dokumencie (np. WorldScript w starszych wersjach MacO), możesz pomyśleć formatów transformacji Unicode jako niepotrzebną złożoność. Ale to znacznie zmniejsza złożoność w porównaniu z wcześniejszymi alternatywami, a każdy format rozwiązuje prawdziwe techniczne ograniczenie. Są również bardzo wydajnie konwertowane między sobą, nie wymagając skomplikowanych tabel odnośników.

JasonTrue
źródło
1
Różne maszyny stanowe JIS i EUC są naprawdę paskudne, i podwójnie, jeśli pracujesz z transformacją między nimi. Unicode znacznie to upraszcza. Jedynym poważnym problemem z Unicode jest, że już mam przestać myśleć bajtów jako znaków, ASCII za pomocą małego znaku-setted szowinista cię!
Donal Fellows
6

Unicode nie został zaprojektowany, aby obejść cały problem posiadania wielu różnych kodowań.

Unicode został zaprojektowany, aby obejść cały numer jednej liczby reprezentujący wiele różnych rzeczy w zależności od używanej strony kodowej. Liczby 0–127 reprezentują te same znaki na dowolnej stronie kodowej Ansi. Jest to również znane jako wykres lub zestaw znaków ASCII. Na stronach kodowych Ansi, które pozwalają na 256 znaków, liczby 128 - 255 reprezentują różne znaki na różnych stronach kodowych.

Na przykład

  • Liczba 57 USD oznacza wielką literę W na wszystkich stronach kodowych, ale
  • Liczba $ EC reprezentuje symbol nieskończoności na stronie kodowej 437 (USA), ale „LATIN MAŁY LITER N Z CEDILLĄ” na stronie kodowej 775 (Bałtyk)
  • Znak Cent ma numer 9B na stronie kodowej 437, ale numer 96 na stronie kodowej 775

To, co zrobił Unicode, wywróciło to wszystko do góry nogami. W Unicode nie ma „ponownego użycia”. Każda liczba reprezentuje pojedynczy unikalny znak. Liczba 00A2 w Unicode jest znakiem cent, a znak cent nie pojawia się nigdzie indziej w definicji Unicode.

Dlaczego więc jest tyle kodowań Unicode? Nawet wiele wersji (zasadniczo) tej samej, takich jak UTF-8, UTF-16 itp.

Nie ma wielu wersji tego samego kodowania. Istnieje wiele kodowań tej samej mapy definicji znaków Unicode, które zostały „wymyślone” w celu zarządzania wymaganiami dotyczącymi przechowywania dla różnych zastosowań różnych płaszczyzn językowych, które istnieją w Unicode.

Unicode definiuje (lub ma spację do zdefiniowania) 4.294.967.295 unikalne znaki. Jeśli chcesz zamapować je na pamięć dyskową / pamięć bez wykonywania konwersji algorytmicznych, potrzebujesz 4 bajtów na znak. Jeśli chcesz przechowywać teksty ze znakami ze wszystkich płaszczyzn językowych, prawdopodobnie potrzebujesz UTF-32 (który jest w zasadzie prostym 1 znakiem - 4 bajtowe kodowanie definicji Unicode).

Ale prawie żaden tekst nie używa znaków ze wszystkich języków. A następnie użycie 4 bajtów na znak wydaje się dużym marnotrawstwem. Zwłaszcza, gdy weźmie się pod uwagę, że większość języków na ziemi jest zdefiniowana w ramach tak zwanego podstawowego języka wielojęzycznego (BMP): pierwsze 65536 liczb w definicji Unicode.

I tam właśnie wszedł UTF-16. Jeśli użyjesz tylko znaków z BMP, UTF-16 zapisze je bardzo skutecznie, wykorzystując tylko dwa bajty na znak. Użyje tylko więcej bajtów dla znaków spoza BMP. Różnica między UTF-16LE (Little Endian) a UTF-16BE (Big Endian) naprawdę ma coś wspólnego z tym, jak liczby są reprezentowane w pamięci komputera (wzorzec bajtów A0oznacza hex 0 A0 lub 0A).

Jeśli twój tekst zawiera jeszcze mniej różnych znaków, jak większość tekstów w językach zachodnioeuropejskich, będziesz chciał jeszcze bardziej ograniczyć wymagania dotyczące przechowywania tekstów. Stąd UTF-8, który wykorzystuje jeden bajt do przechowywania znaków obecnych na wykresie ASCII (pierwsze 128 cyfr) oraz wybór spośród znaków Ansi (drugie 128 cyfr różnych stron kodowych). Będzie używać więcej bajtów dla znaków spoza tego zestawu „najczęściej używanych znaków”.

Podsumowując:

  • Unicode to odwzorowanie znaków we wszystkich językach na ziemi (i niektórych Klingon do uruchomienia), a następnie niektórych (matematycznych, muzycznych itp.) Na unikalny numer.
  • Kodowanie to algorytmy zdefiniowane do przechowywania tekstów z wykorzystaniem numerów tej unikalnej mapy znaków tak efektywnie, jak to możliwe, biorąc pod uwagę „przeciętne użycie” znaków w tekstach.
Marjan Venema
źródło
2
„Cyfry 0–127 oznaczają te same znaki na dowolnej stronie kodowej”. - cóż, chyba że mówisz EBCDIC, w którym $57to przypadku nie jest W
MSalters
@MSalters: masz absolutną rację. EBCDIC jest inny (i są też inne EBCDIC). Wydaje mi się, że moje dni na komputerze mainframe są tak długo za mną, że nie pamiętam, albo zbyt mocno i zbyt długo tłumiłem te wspomnienia ... :-)
Marjan Venema
„Cyfry 0–127 oznaczają te same znaki na dowolnej stronie kodowej”. W rzeczywistości istnieją kodowania, takie jak BinarySignWriting, które nie są nadzbiorami ASCII. BinarySignWriting w rzeczywistości nie zawiera żadnych znaków ASCII.
TRiG
@TRiG: Właśnie dlatego zredagowałem moje oświadczenie, aby dotyczyło stron kodowych Ansi. Musiałeś to zrobić, zanim się odświeżyłeś ...
Marjan Venema
Tak. Podczas pisania komentarza został dodany dodatkowy komentarz i aktualizacja posta. Mimo to BinarySignWriting jest interesujący.
TRiG
2

Unicode definiuje mapę między cyframi i znakami. Jednak gdy wysyłasz numer do odbiornika, nadal musisz zdefiniować sposób reprezentowania tego numeru. Po to jest UTF. Określa, jak reprezentować liczbę w strumieniu bajtów.

Codism
źródło
2

Uzasadnienie UTF-32 jest proste: jest to najprostsza reprezentacja punktów kodu Unicode. Dlaczego więc nie wszystko w UTF-32? Dwa główne powody:

Jeden to rozmiar . UTF-32 wymaga 4 bajtów na każdy znak. W przypadku tekstu zawierającego tylko znaki w Podstawowym miejscu wielojęzycznym jest to dwa razy więcej miejsca niż UTF-16. W przypadku tekstu angielskiego jest to 4 razy więcej miejsca niż w US-ASCII.

Głównym powodem jest kompatybilność wsteczna . Każde kodowanie Unicode inne niż „niezakodowane” UTF-32 zostało zaprojektowane pod kątem zgodności z poprzednimi standardami.

  • UTF-8: Kompatybilność wsteczna z US-ASCII.
  • UTF-16: Kompatybilność wsteczna z UCS-2 (16-bitowy Unicode, zanim został rozszerzony poza BMP).
  • UTF-7: Kompatybilność wsteczna z serwerami pocztowymi nieobsługującymi 8-bitów.
  • GB18030: Kompatybilność wsteczna z kodowaniem GB2312 i GBK dla języka chińskiego.
  • UTF-EBCDIC: Kompatybilność wsteczna z podstawowym podzbiorem łacińskim EBCDIC.

Myślałem, że Unicode został zaprojektowany, aby obejść cały problem posiadania wielu różnych kodowań

Tak było i tak było. Znacznie łatwiej jest przekonwertować pomiędzy UTF-8, -16 i -32, niż radzić sobie ze starym systemem setek różnych kodowań znaków dla różnych języków i różnych systemów operacyjnych.

dan04
źródło
1

Wiesz, że plik zip może skompresować plik, który jest znacznie mniejszy (zwłaszcza tekst), a następnie rozpakować go do identycznej kopii oryginalnego pliku.

Algorytm zipowania ma w rzeczywistości kilka różnych algorytmów o różnych charakterystykach do wyboru: przechowywane (bez kompresji), zmniejszone, zmniejszone (metody 1-4), wszczepione, tokenizacja, deflacja, deflate64, BZIP2, LZMA (EFS), WavPack, PPMd, gdzie teoretycznie może wypróbować wszystkie z nich i wybrać najlepszy wynik, ale zwykle wystarczy użyć Deflated.

UTF działa w podobny sposób. Istnieje kilka algorytmów kodowania, z których każdy ma inną charakterystykę, ale zwykle wybierasz UTF-8, ponieważ jest on szeroko obsługiwany w przeciwieństwie do innych wariantów UTF, co z kolei jest zgodne bitowo z 7-bitowym ASCII, co ułatwia używać na większości nowoczesnych platform komputerowych, które zwykle używają 8-bitowego rozszerzenia ASCII.


źródło
Pytanie: Różnica w stosunku do pliku zip polega na tym, że istnieje nagłówek informujący o tym, jaka kompresja działa. W przypadku plików tekstowych nadal musimy zgadywać, prawda?
Matthew Scharley
Istnieje specjalna sekwencja, która dokładnie to mówi. Ze względu na kompatybilność wsteczną z ASCII jest ona opcjonalna.