UTF-16 - UTF-16

UTF-16
Pełna mapa Unifont.png
Pierwsze 2 16 punktów kodowych Unicode. Szary pasek u dołu to zastępcze połówki używane przez UTF-16 (biały obszar poniżej paska to obszar prywatnego użytku )
Języki) Międzynarodowy
Standard Standard Unicode
Klasyfikacja Format transformacji Unicode , kodowanie o zmiennej szerokości
Rozszerza LUW-2
Przekształca / koduje ISO 10646 ( Unikod )

UTF-16 ( 16-bitowy format transformacji Unicode ) to kodowanie znaków zdolne do kodowania wszystkich 1112 064 ważnych punktów kodowych znaków Unicode (w rzeczywistości ta liczba punktów kodowych jest podyktowana projektem UTF-16). Kodowanie ma zmienną długość , ponieważ punkty kodowe są zakodowane za pomocą jednej lub dwóch 16-bitowych jednostek kodu . UTF-16 powstał z wcześniejszego przestarzałego 16-bitowego kodowania o stałej szerokości, znanego obecnie jako UCS-2 (od 2-bajtowego uniwersalnego zestawu znaków), gdy stało się jasne, że potrzeba więcej niż 2 16 (65 536) punktów kodowych.

UTF-16 jest używany wewnętrznie przez systemy takie jak Microsoft Windows , język programowania Java i JavaScript /ECMAScript. Jest również często używany do zwykłego tekstu i plików danych do przetwarzania tekstu w systemie Microsoft Windows. Jest rzadko używany do plików w systemach uniksopodobnych. Od maja 2019 r. Microsoft zmienił kurs, kładąc nacisk tylko na UTF-16 dla Unicode; w przypadku aplikacji Windows firma Microsoft zaleca i obsługuje kodowanie UTF-8 (np. dla aplikacji Universal Windows Platform (UWP)).

UTF-16 jest jedynym kodowaniem internetowym niekompatybilnym z ASCII i nigdy nie zyskał popularności w sieci, gdzie jest używany przez mniej niż 0,002% (nieco ponad 1 tysięczna z 1 procenta) stron internetowych. Dla porównania UTF-8 jest używany przez 97% wszystkich stron internetowych. Grupa Web Hypertext Application Technology Working (WHATWG) uważa, UTF-8 „obowiązkową kodowanie dla wszystkich [tekstu]” i że ze względów bezpieczeństwa aplikacji przeglądarka nie powinno się używać UTF-16.

Historia

Pod koniec lat 80. rozpoczęto prace nad opracowaniem jednolitego kodowania dla „Universal Character Set” ( UCS ), które zastąpiłoby wcześniejsze kodowanie specyficzne dla języka jednym skoordynowanym systemem. Celem było uwzględnienie wszystkich wymaganych znaków z większości języków świata, a także symboli z dziedzin technicznych, takich jak nauka, matematyka i muzyka. Pierwotnym pomysłem było zastąpienie typowego 256-znakowego kodowania, które wymagało 1 bajtu na znak, kodowaniem wykorzystującym 65 536 (2 16 ) wartości, które wymagałoby 2 bajtów (16 bitów) na znak.

Pracowały nad tym równolegle dwie grupy, ISO/IEC JTC 1/SC 2 oraz Unicode Consortium , ta ostatnia reprezentująca głównie producentów sprzętu komputerowego. Dwie grupy próbowały zsynchronizować swoje przypisania znaków, aby rozwijające się kodowania były wzajemnie kompatybilne. Wczesne kodowanie 2-bajtowe nosiło nazwę „Unicode”, ale teraz nazywa się „UCS-2”.

Kiedy stawało się coraz bardziej jasne, że 2 16 znaków nie wystarczy, IEEE wprowadził większą 31-bitową przestrzeń i kodowanie ( UCS-4 ), które wymagałoby 4 bajtów na znak. Konsorcjum Unicode sprzeciwiło się temu , zarówno dlatego, że 4 bajty na znak marnowały dużo pamięci i miejsca na dysku, jak i dlatego, że niektórzy producenci już mocno zainwestowali w technologię 2 bajtów na znak. Schemat kodowania UTF-16 został opracowany jako kompromis i wprowadzony w wersji 2.0 standardu Unicode w lipcu 1996 roku. Jest on w pełni określony w RFC 2781, opublikowanym w 2000 roku przez IETF .

W kodowaniu UTF-16 punkty kodowe mniejsze niż 216 są kodowane za pomocą pojedynczej 16-bitowej jednostki kodu równej wartości liczbowej punktu kodowego, tak jak w starszym UCS-2. Nowsze punkty kodowe większe lub równe 2 16 są kodowane przez wartość złożoną przy użyciu dwóch 16-bitowych jednostek kodu. Te dwie 16-bitowe jednostki kodu są wybierane z zastępczego zakresu UTF-16 0xD800–0xDFFF, który nie był wcześniej przypisany do znaków. Wartości z tego zakresu nie są używane jako znaki, a UTF-16 nie zapewnia legalnego sposobu kodowania ich jako pojedynczych punktów kodowych. Strumień UTF-16 składa się zatem z pojedynczych 16-bitowych punktów kodowych poza zakresem zastępczym dla punktów kodowych w podstawowej płaszczyźnie wielojęzycznej (BMP) i par wartości 16-bitowych w zakresie zastępczym dla punktów kodowych powyżej BMP.

UTF-16 jest określony w najnowszych wersjach zarówno międzynarodowego standardu ISO/IEC 10646, jak i standardu Unicode. „UCS-2 należy teraz uznać za przestarzałe. Nie odnosi się już do formy kodowania w 10646 ani w standardzie Unicode”. Od 2021 r. nie ma planów rozszerzenia UTF-16 o obsługę większej liczby punktów kodowych lub punktów kodowych zastępowanych przez surogaty, ponieważ naruszyłoby to politykę stabilności Unicode w odniesieniu do kategorii ogólnej lub zastępczych punktów kodowych. (Każdy schemat, który pozostaje kodem samosynchronizującym, wymagałby przydzielenia co najmniej jednego punktu kodu BMP, aby rozpocząć sekwencję. Zmiana celu punktu kodu jest niedozwolona.)

Opis

Każdy punkt kodowy Unicode jest zakodowany jako jedna lub dwie 16-bitowe jednostki kodu . Sposób, w jaki te 16-bitowe kody są przechowywane jako bajty, zależy od „ endianowości ” pliku tekstowego lub protokołu komunikacyjnego.

Zapisanie „znaku” może wymagać od dwóch do czternastu lub nawet więcej bajtów. Na przykład znak flagi emoji zajmuje 8 bajtów, ponieważ jest „zbudowany z pary wartości skalarnych Unicode” (a te wartości są poza BMP i wymagają 4 bajtów każda).

U+0000 do U+D7FF i U+E000 do U+FFFF

Zarówno UTF-16, jak i UCS-2 kodują punkty kodowe w tym zakresie jako pojedyncze 16-bitowe jednostki kodu, które są liczbowo równe odpowiednim punktom kodowym. Te punkty kodowe w Basic Multilingual Plane (BMP) są jedynymi punktami kodowymi, które mogą być reprezentowane w UCS-2. Począwszy od Unicode 9.0, niektóre współczesne niełacińskie skrypty azjatyckie, bliskowschodnie i afrykańskie wykraczają poza ten zakres, podobnie jak większość znaków emoji .

Punkty kodowe od U+010000 do U+10FFFF

Punkty kodowe z innych płaszczyzn (zwanych Płaszczyznami Uzupełniającymi ) są zakodowane jako dwie 16-bitowe jednostki kodu zwane parą zastępczą , według następującego schematu:

Dekoder UTF-16
Niski
Wysoka
DC00 DC01    ...    DFFF
D800 010000 010001 ... 0103FF
D801 010400 010401 ... 0107FF
  ⋮
DBFF 10FC00 10FC01 ... 10FFFF
  • 0x10000 jest odejmowane od punktu kodowego (U) , pozostawiając 20-bitową liczbę (U') w zakresie liczb szesnastkowych 0x00000–0xFFFFF. Uwaga dla tych celów, U jest zdefiniowane jako nie większe niż 0x10FFFF.
  • Pierwsze dziesięć bitów (w zakresie 0x000–0x3FF) jest dodawanych do 0xD800, aby otrzymać pierwszą 16-bitową jednostkę kodu lub wysoki surogat (W1) , który będzie mieścił się w zakresie 0xD800–0xDBFF .
  • Młodsze dziesięć bitów (również z zakresu 0x000–0x3FF) jest dodawanych do 0xDC00, aby otrzymać drugą 16-bitową jednostkę kodu lub niski surogat (W2) , który będzie mieścił się w zakresie 0xDC00–0xDFFF .

Zilustrowany wizualnie rozkład U' pomiędzy W1 i W2 wygląda następująco:

U' = yyyyyyyyyyxxxxxxxxxx  // U - 0x10000
W1 = 110110yyyyyyyyyy      // 0xD800 + yyyyyyyyyy
W2 = 110111xxxxxxxxxx      // 0xDC00 + xxxxxxxxxx

Wysokiej zastępczym i niskiej zastępczym , znane są również jako „wiodący” i „tylny” zastępcze, odpowiednio analogicznych do natarcia i spływu bajtów UTF-8.

Ponieważ zakresy dla wysokich surogatów ( 0xD800–0xDBFF ), niskich surogatów ( 0xDC00–0xDFFF ) i prawidłowych znaków BMP (0x0000–0xD7FF, 0xE000–0xFFFF) są rozłączne , nie jest możliwe, aby surogat pasował do znaku BMP, lub aby dwie sąsiednie jednostki kodu wyglądały jak legalna para zastępcza . To znacznie upraszcza wyszukiwanie. Oznacza to również, że UTF-16 synchronizuje się samoczynnie na słowach 16-bitowych: to, czy jednostka kodu rozpoczyna znak, można określić bez badania wcześniejszych jednostek kodu (tj. typ jednostki kodu można określić na podstawie zakresów wartości, w których spada). UTF-8 ma te zalety, ale wiele wcześniejszych schematów kodowania wielobajtowego (takich jak Shift JIS i inne azjatyckie kodowania wielobajtowe) nie pozwalało na jednoznaczne wyszukiwanie i mogło być zsynchronizowane tylko przez ponowne parsowanie od początku ciągu (UTF -16 nie synchronizuje się samoczynnie, jeśli jeden bajt zostanie utracony lub jeśli przechodzenie rozpoczyna się od losowego bajtu).

Ponieważ wszystkie najczęściej używane znaki znajdują się w BMP, obsługa par zastępczych często nie jest dokładnie testowana. Prowadzi to do trwałych błędów i potencjalnych luk w zabezpieczeniach, nawet w popularnych i dobrze sprawdzonych aplikacjach (np. CVE - 2008-2938 , CVE - 2012-2135 ).

Do płaszczyzn uzupełniające zawierają emoji skrypty historycznych, mniej stosowanych symboli, mniej stosowanych chińskich ideogramom itp Ponieważ kodowanie płaszczyznach uzupełniające zawiera 20 znaczących bitów (10, 16 bitów w każdym z wysokiego i niskiego zastępcze ), 2 20 punktów szyfrowego być zakodowane, podzielone na 16 płaszczyzn po 2 16 punktów kodowych każda. Łącznie z oddzielnie obsługiwaną płaszczyzną Basic Multilingual Plane istnieje łącznie 17 samolotów.

U+D800 do U+DFFF

Standard Unicode na stałe rezerwuje te wartości punktów kodowych dla kodowania UTF-16 dla wysokich i niskich surogatów i nigdy nie zostanie im przypisany znak, więc nie powinno być powodu, aby je kodować. Oficjalny standard Unicode mówi, że żadne formularze UTF, w tym UTF-16, nie mogą kodować tych punktów kodowych.

Jednak UCS-2, UTF-8 i UTF-32 mogą kodować te punkty kodowe w trywialny i oczywisty sposób, a robi to duża ilość oprogramowania, mimo że norma stwierdza, że ​​takie rozwiązania należy traktować jako błędy kodowania.

Możliwe jest jednoznaczne zakodowanie niesparowanego zastępczego punktu kodowego (wysoki zastępczy punkt kodowy, po którym nie występuje niski lub niski nie poprzedzony wysokim) w formacie UTF-16 przy użyciu jednostki kodu równej punktowi kodowemu . Wynik nie jest prawidłowym kodowaniem UTF-16, ale większość implementacji kodera i dekodera UTF-16 robi to wtedy podczas tłumaczenia między kodowaniami. System Windows dopuszcza niesparowane zastępniki w nazwach plików i innych miejscach, co ogólnie oznacza, że ​​muszą one być obsługiwane przez oprogramowanie, pomimo ich wykluczenia ze standardu Unicode.

Przykłady

Aby zakodować U+10437 (𐐷) do UTF-16:

  • Odejmij 0x10000 od punktu kodowego, pozostawiając 0x0437.
  • Dla wysokiego zastępcy, przesuń w prawo o 10 (podziel przez 0x400), a następnie dodaj 0xD800, co daje 0x0001 + 0xD800 = 0xD801.
  • W przypadku dolnego surogatu weź najmniejsze 10 bitów (pozostało z dzielenia przez 0x400), a następnie dodaj 0xDC00, co daje 0x0037 + 0xDC00 = 0xDC37.

Aby zdekodować U+10437 (𐐷) z UTF-16:

  • Weź wysoki surogat (0xD801) i odejmij 0xD800, a następnie pomnóż przez 0x400, otrzymując 0x0001 × 0x400 = 0x0400.
  • Weź niski surogat (0xDC37) i odejmij 0xDC00, co daje 0x37.
  • Dodaj te dwa wyniki razem (0x0437), a na koniec dodaj 0x10000, aby uzyskać końcowy zdekodowany punkt kodowy UTF-32, 0x10437.

Poniższa tabela podsumowuje tę konwersję, a także inne. Kolory wskazują, jak bity z punktu kodowego są rozłożone między bajtami UTF-16. Dodatkowe bity dodane przez proces kodowania UTF-16 są pokazane na czarno.

Postać Binarny punkt kodowy Binarny UTF-16
Jednostki kodu szesnastkowego UTF-16

Szesnastkowe bajty UTF-16BE

Szesnastkowe bajty UTF-16LE
$ U+0024 0000 0000 0010 0100 0000 0000 0010 0100 0024 00 24 24 00
U+20AC 0010 0000 1010 1100 0010 0000 1010 1100 20AC 20 AC AC 20
𐐷 U+10437 0001 0000 0100 0011 0111 1101 1000 0000 0001 1101 1100 0011 0111 D801 DC37 D8 01 DC 37 01 D8 37 DC
𤭢 U+24B62 0010 0100 1011 0110 0010 1101 1000 0101 0010 1101 1111 0110 0010 D852 DF62 D8 52 DF 62 52 D8 62 DF

Schematy kodowania w kolejności bajtów

UTF-16 i UCS-2 tworzą sekwencję 16-bitowych jednostek kodu. Ponieważ większość protokołów komunikacyjnych i pamięciowych jest zdefiniowana dla bajtów, a zatem każda jednostka zajmuje dwa 8-bitowe bajty, kolejność bajtów może zależeć od endianowości (kolejności bajtów) architektury komputera.

Aby pomóc w rozpoznawaniu porządek bajtów jednostek kodowych UTF-16 pozwala Byte Order Mark (BOM), punkt kod o wartości U + FEFF, aby poprzedzać pierwszy rzeczywistej wartości kodowane. (U+FEFF jest niewidocznym znakiem spacji nierozdzielającej o zerowej szerokości /ZWNBSP.) Jeśli architektura endian dekodera jest zgodna z architekturą kodera, dekoder wykrywa wartość 0xFEFF, ale dekoder przeciwnego końca interpretuje BOM jako nieznakowa wartość U+FFFE zarezerwowana do tego celu. Ten niepoprawny wynik zawiera wskazówkę dotyczącą wymiany bajtów dla pozostałych wartości.

Jeśli brakuje BOM, RFC 2781 zaleca przyjęcie kodowania big-endian. W praktyce, ze względu na to, że Windows domyślnie używa kolejności little-endian, wiele aplikacji zakłada kodowanie little-endian. Niezawodne jest również wykrywanie endianowości poprzez wyszukiwanie bajtów null, przy założeniu, że znaki mniejsze niż U+0100 są bardzo powszechne. Jeśli więcej parzystych bajtów (zaczynając od 0) ma wartość null, to jest to big-endian.

Standard pozwala również na wyraźne określenie kolejności bajtów poprzez określenie UTF-16BE lub UTF-16LE jako typu kodowania. Gdy kolejność bajtów jest wyraźnie określona w ten sposób, BOM nie powinien być dodawany do tekstu, a U+FEFF na początku powinien być traktowany jako znak ZWNBSP. Większość aplikacji ignoruje BOM we wszystkich przypadkach pomimo tej reguły.

W przypadku protokołów internetowych IANA zatwierdziła „UTF-16”, „UTF-16BE” i „UTF-16LE” jako nazwy tych kodowań (w nazwach nie jest rozróżniana wielkość liter). Aliasy UTF_16 lub UTF16 mogą mieć znaczenie w niektórych językach programowania lub aplikacjach, ale nie są to standardowe nazwy w protokołach internetowych.

Podobne oznaczenia, UCS-2BE i UCS-2LE , są używane do pokazywania wersji UCS-2 .

Stosowanie

UTF-16 jest używany dla tekstu w OS API wszystkich obecnie obsługiwanych wersji Microsoft Windows (włączając przynajmniej wszystkie od Windows CE / 2000 / XP / 2003 / Vista / 7 ), włączając Windows 10 . W systemie Windows XP żaden punkt kodowy powyżej U+FFFF nie jest zawarty w żadnej czcionce dostarczanej z systemem Windows dla języków europejskich. Starsze systemy Windows NT (przed Windows 2000) obsługują tylko UCS-2. Pliki i dane sieciowe są zwykle mieszanką kodowań UTF-16, UTF-8 i starszych bajtów.

Chociaż istniało pewne wsparcie UTF-8 nawet dla systemu Windows XP, zostało ono ulepszone (w szczególności możliwość nadawania nazwy plikowi za pomocą UTF-8) w Windows 10 Insider build 17035 i aktualizacja z kwietnia 2018 r., a od maja 2019 r. Microsoft zaleca oprogramowanie użyj go zamiast UTF-16.

System operacyjny IBM i wyznacza CCSID ( strona kodowa ) 13488 dla kodowania UCS-2 i CCSID 1200 dla kodowania UTF-16, chociaż system traktuje je jako UTF-16.

UTF-16 jest używany przez systemy operacyjne Qualcomm BREW ; z NET środowisk; oraz wieloplatformowy zestaw narzędzi graficznych Qt .

Symbian OS używany w telefonach Nokia S60 i telefonach Sony Ericsson UIQ wykorzystuje UCS-2. Telefony iPhone używają UTF-16 do obsługi krótkich wiadomości zamiast UCS-2 opisanego w standardach 3GPP TS 23.038 ( GSM ) i IS-637 ( CDMA ).

System plików Joliet , używany na nośnikach CD-ROM , koduje nazwy plików przy użyciu UCS-2BE (do sześćdziesięciu czterech znaków Unicode na nazwę pliku).

Środowisko językowe Python oficjalnie używa tylko wewnętrznie UCS-2 od wersji 2.0, ale dekoder UTF-8 do "Unicode" daje poprawny kod UTF-16. Od Pythona 2.2 obsługiwane są "szerokie" kompilacje Unicode, które zamiast tego używają UTF-32; są one używane głównie w systemie Linux. Python 3.3 nie używa już UTF-16, zamiast tego kodowanie, które daje najbardziej zwartą reprezentację danego ciągu, jest wybierane spośród ASCII/Latin-1, UCS-2 i UTF-32.

Java pierwotnie używała UCS-2 i dodała obsługę dodatkowych znaków UTF-16 w J2SE 5.0 .

JavaScript może używać UCS-2 lub UTF-16. Od ES2015 metody ciągów i flagi wyrażeń regularnych zostały dodane do języka, który umożliwia obsługę ciągów z perspektywy niezależnej od kodowania.

W wielu językach łańcuchy w cudzysłowie wymagają nowej składni do cytowania znaków innych niż BMP, ponieważ "\uXXXX"składnia w stylu C wyraźnie ogranicza się do 4 cyfr szesnastkowych. Poniższe przykłady ilustrują składnię znaku „𝄞” innego niż BMP (U+1D11E, MUSICAL SYMBOL G CLEF). Najpopularniejszym (używanym przez C++ , C# , D i kilka innych języków) jest użycie wielkiej litery „U” z 8 cyframi szesnastkowymi, takimi jak "\U0001D11E". W wyrażeniach regularnych Java 7, ICU i Perl, "\x{1D11E}"należy użyć składni ; podobnie w ECMAScript 2015 (JavaScript) formatem ucieczki jest "\u{1D11E}". W wielu innych przypadkach (takich jak Java poza wyrażeniami regularnymi) jedynym sposobem na uzyskanie znaków innych niż BMP jest indywidualne wprowadzenie połówek zastępczych, na przykład: "\uD834\uDD1E"dla U+1D11E.

Implementacje ciągów oparte na UTF-16 zazwyczaj definiują długość ciągu i umożliwiają indeksowanie w kategoriach tych 16-bitowych jednostek kodu , a nie w kategoriach punktów kodowych. Ani punkty kodowe, ani jednostki kodu nie odpowiadają niczemu, co użytkownik końcowy może rozpoznać jako „znak”; rzeczy, które użytkownicy identyfikują jako znaki, mogą ogólnie składać się z podstawowego punktu kodowego i sekwencji łączących się znaków (lub może być sekwencją punktów kodowych innego rodzaju, na przykład Hangul łączący jamos) – Unicode odnosi się do tej konstrukcji jako grafemu klaster  – i jako takie, aplikacje obsługujące ciągi znaków Unicode, bez względu na kodowanie, muszą radzić sobie z faktem, że ogranicza to ich zdolność do arbitralnego dzielenia i łączenia ciągów.

UCS-2 jest również obsługiwany przez język PHP i MySQL.

Swift , wersja 5, preferowany język aplikacji Apple, został zmieniony z UTF-16 na UTF-8 jako preferowane kodowanie.

Zobacz też

Uwagi

Bibliografia

Zewnętrzne linki