UTF-8 - UTF-8

UTF-8
Standard Standard Unicode
Klasyfikacja Format transformacji Unicode , rozszerzony ASCII , kodowanie o zmiennej szerokości
Rozszerza US-ASCII
Przekształca / koduje ISO 10646 ( Unikod )
Poprzedzony UTF-1

UTF-8 to kodowanie znaków o zmiennej szerokości używane do komunikacji elektronicznej. Zdefiniowana przez standard Unicode, nazwa pochodzi od formatu transformacji Unicode (lub Universal Coded Character Set ) – 8-bit .

UTF-8 jest w stanie zakodować wszystkie 1112 064 poprawnych punktów kodowych znaków w Unicode przy użyciu od jednej do czterech jednobajtowych (8-bitowych) jednostek kodu. Punkty kodowe o niższych wartościach liczbowych, które występują częściej, są kodowane przy użyciu mniejszej liczby bajtów. Został zaprojektowany z myślą o wstecznej kompatybilności z ASCII : pierwsze 128 znaków Unicode, które odpowiadają jeden do jednego z ASCII, są zakodowane przy użyciu jednego bajtu o tej samej wartości binarnej co ASCII, dzięki czemu poprawny tekst ASCII jest poprawny UTF-8 - zakodowany również Unicode. Ponieważ bajty ASCII nie występują podczas kodowania punktów kodowych innych niż ASCII do UTF-8, UTF-8 można bezpiecznie używać w większości języków programowania i dokumentów, które interpretują niektóre znaki ASCII w specjalny sposób, na przykład /( ukośnik ) w nazwach plików \( ukośnikowe ) w sekwencje , i %w printf .

UTF-8 został zaprojektowany jako doskonała alternatywa dla UTF-1 , proponowanego kodowania o zmiennej szerokości z częściową kompatybilnością ASCII, której brakowało niektórych funkcji, w tym samosynchronizacji i pełnej obsługi znaków ASCII, takich jak ukośniki. Ken Thompson i Rob Pike opracowali pierwszą implementację systemu operacyjnego Plan 9 we wrześniu 1992 roku. Doprowadziło to do jej przyjęcia przez X/Open jako specyfikacji dla FSS-UTF , która została po raz pierwszy oficjalnie zaprezentowana na USENIX w styczniu 1993 roku, a następnie zaakceptowana. przez Internet Engineering Task Force (IETF) w RFC 2277 ( BCP 18 ) dla przyszłych standardów internetowych, zastępując zestawy znaków jednobajtowych, takie jak Latin-1 w starszych dokumentach RFC.

UTF-8 jest zdecydowanie najpopularniejszym kodowaniem w sieci WWW , stanowiąc ponad 97% wszystkich stron internetowych i do 100% w przypadku niektórych języków od 2021 r.

Nazewnictwo

Oficjalny kod IANA ( Internet Assigned Numbers Authority ) do kodowania to „UTF-8”. Wszystkie litery są pisane wielkimi literami, a nazwa jest dzielona. Ta pisownia jest używana we wszystkich dokumentach Unicode Consortium dotyczących kodowania.

Alternatywnie nazwa „ utf-8 ” może być używana przez wszystkie standardy zgodne z listą IANA (w tym nagłówki CSS , HTML , XML i HTTP ), ponieważ w deklaracji nie jest rozróżniana wielkość liter.

Inne warianty, takie jak te, które pomijają myślnik lub zastępują go spacją, tj. „ utf8 ” lub „ UTF 8 ”, nie są akceptowane jako poprawne przez obowiązujące normy. Mimo to większość przeglądarek internetowych potrafi je zrozumieć, dlatego standardy mające na celu opisanie istniejących praktyk (takich jak HTML5) mogą skutecznie wymagać ich rozpoznania.

Nieoficjalnie, UTF-8-BOM i UTF-8-NOBOM są czasami używane do plików tekstowych, które zawierają lub nie zawierają odpowiednio znacznika kolejności bajtów (BOM). Szczególnie w Japonii kodowanie UTF-8 bez BOM jest czasami nazywane „ UTF-8N ”.

Windows XP i nowsze, w tym wszystkie obsługiwane wersje Windows, mają stronę kodową 65001 , jako synonim UTF-8 (ponieważ obsługa UTF-8 w Windows 7 jest lepsza), a Microsoft ma skrypt dla Windows 10 , aby włączyć go domyślnie dla jego program Microsoft Notepad .

W PCL UTF-8 jest nazywany Symbol-ID „18N” (PCL obsługuje 183 kodowania znaków, zwane zestawami symboli, które potencjalnie można zredukować do jednego, 18N, czyli UTF-8).

Kodowanie

Ponieważ ograniczenie przestrzeni kodu Unicode do wartości 21-bitowych w 2003 r., UTF-8 jest zdefiniowany do kodowania punktów kodowych w jednym do czterech bajtów, w zależności od liczby znaczących bitów w wartości numerycznej punktu kodowego. Poniższa tabela przedstawia strukturę kodowania. W x znaków są zastępowane przez bity punktu kodowego.

Punkt kodowy <-> konwersja UTF-8
Pierwszy punkt kodowy Ostatni punkt kodowy Bajt 1 Bajt 2 Bajt 3 Bajt 4
U+0000 U+007F 0xxxxxxx
U+0080 U+07FF 110xxxxx 10xxxxxx
U+0800 U+FFFF 1110xxxx 10xxxxxx 10xxxxxx
U+10000 U+10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

Pierwsze 128 znaków (US-ASCII) wymaga jednego bajtu. Kolejne 1,920 znaków potrzebujemy dwóch bajtów do zakodowania, która obejmuje pozostałą część niemal wszystkich alfabetów posługujących się alfabetem łacińskim , a także rozszerzeń IPA , greckiego , cyrylicy , koptyjskich , ormiańskich , hebrajskich , arabskimi , Syryjski , Thaana i Pismo n'ko alfabetów, a także jako kombinacje znaków diakrytycznych . Trzy bajty są potrzebne dla znaków w pozostałej części Basic Multilingual Plane , która zawiera praktycznie wszystkie powszechnie używane znaki, w tym większość znaków chińskich, japońskich i koreańskich . Cztery bajty są potrzebne dla znaków w innych płaszczyznach Unicode , które obejmują mniej popularne znaki CJK , różne skrypty historyczne, symbole matematyczne i emoji (symbole piktograficzne).

„Znak” może w rzeczywistości zająć więcej niż 4 bajty, np. znak flagi emoji zajmuje 8 bajtów, ponieważ jest „zbudowany z pary wartości skalarnych Unicode”.

Przykłady

Rozważ kodowanie znaku Euro , €:

  1. Punkt kodowy Unicode dla „€” to U+20AC.
  2. Ponieważ ten punkt kodowy leży między U+0800 a U+FFFF, zakodowanie zajmie trzy bajty.
  3. Szesnastkowy 20AC jest binarny 0010 0000 10 10 1100 . Dwa wiodące zera są dodawane, ponieważ kodowanie trzybajtowe wymaga dokładnie szesnastu bitów od punktu kodowego.
  4. Ponieważ kodowanie będzie miało długość trzech bajtów, jego bajt wiodący zaczyna się od trzech jedynek, a następnie 0 ( 1110... )
  5. Cztery najbardziej znaczące bity punktu kodowego są przechowywane w pozostałych czterech bitach niższego rzędu tego bajtu ( 1110 0010 ), pozostawiając 12 bitów punktu kodowego do zakodowania ( ... 0000 10 10 1100 ).
  6. Wszystkie bajty kontynuacji zawierają dokładnie sześć bitów od punktu kodowego. Tak więc następnych sześć bitów punktu kodowego jest przechowywanych w najniższych sześciu bitach następnego bajtu, a 10 jest przechowywanych w wyższych dwóch bitach, aby oznaczyć go jako bajt kontynuacji (czyli 10 000010 ).
  7. W końcu ostatnie sześć bitów punktu kodowego jest przechowywanych w młodszych sześciu bitach ostatniego bajtu i ponownie 10 jest przechowywanych w starszych dwóch bitach ( 10 101100 ).

Trzy bajty 1110 0010 10 000010 10 101100 może być bardziej zwięźle napisany w systemie szesnastkowym , jak E2 82 AC .

Poniższa tabela podsumowuje tę konwersję, a także inne o różnych długościach w UTF-8. Kolory wskazują, jak bity z punktu kodowego są rozłożone między bajtami UTF-8. Dodatkowe bity dodane przez proces kodowania UTF-8 są wyświetlane na czarno.

Przykłady kodowania UTF-8
Postać Binarny punkt kodowy Binarny UTF-8 Szesnastkowy UTF-8
$ U+0024 010 0100 0 0100100 24
¢ U+00A2 000 10 10 0010 110 00010 10 100010 C2 A2
U+0939 0000 1001 00 11 1001 1110 0000 10 100100 10 111001 E0 A4 B9
U+20AC 0010 0000 10 10 1100 1110 0010 10 +000.010 10 101100 E2 82 AC
U+D55C 1101 0101 01 01 1100 1110 1101 10 010101 10 011100 ED 95 9C
𐍈 U+10348 0 00 01 0000 0011 01 00 1000 11110 000 10 010000 10 001101 10 001000 F0 90 8D 88

ósemkowy

Użycie w UTF-8 sześciu bitów na bajt do reprezentowania rzeczywistych kodowanych znaków oznacza, że notacja ósemkowa (używająca 3-bitowych grup) może pomóc w porównywaniu sekwencji UTF-8 ze sobą oraz w ręcznej konwersji.

Ósemkowy punkt kodowy <-> ósemkowa konwersja UTF-8
Pierwszy punkt kodowy Ostatni punkt kodowy Punkt kodowy Bajt 1 Bajt 2 Bajt 3 Bajt 4
000 177 XXX XXX
0200 3777 xxyy 3xx 2yy
04000 77777 xyyzz 34x 2yy 2zz
100000 177777 1xyyzz 35x 2yy 2zz
0200000 4177777 xyyzzww 36x 2yy 2zz 2ww

W notacji ósemkowej dowolne cyfry ósemkowe, oznaczone w tabeli jako x, y, z lub w, pozostaną niezmienione podczas konwersji do lub z UTF-8.

Przykład: Á = U+00C1 = 0301 (ósemkowo) jest zakodowane jako 303 201 w UTF-8 (C3 81 w kodzie szesnastkowym).
Przykład: € = U+20AC = 20254 jest zakodowane jako 342 202 254 w UTF-8 (E2 82 AC w ​​hex).

Układ strony kodowej

W poniższej tabeli podsumowano użycie jednostek kodu UTF-8 (pojedynczych bajtów lub oktetów ) w formacie strony kodowej . Górna połowa ( 0_ do 7_ ) jest przeznaczona dla bajtów używanych tylko w kodach jednobajtowych, więc wygląda jak normalna strona kodowa; dolna połowa jest przeznaczona dla bajtów kontynuacji ( 8_ do B_ ) i bajtów wiodących ( C_ do F_ ) i jest wyjaśniona dalej w legendzie poniżej.

UTF-8
_0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _A _B _C _D _MI _F
(1 bajt)
0_
NUL
0000
SOH
0001
STX
0002
ETX
0003
EOT
0004
ENQ
0005
ACK
0006
BEL
0007
BS
0008
HT
0009
LF
000A
VT
000B
FF
000C
CR
000D
SO
000E
SI
000F
(1)
1_
DLE
0010
DC1
0011
DC2
0012
DC3
0013
DC4
0014
NAK
0015
SYN
0016
ETB
0017
MOŻE
0018
EM
0019
SUB
001A
ESC
001B
FS
001C
GS
001D
RS
001E
USA
001F
(1)
2_
SP
0020
!
0021

0022
#
0023
0024
%
0025
&
0026
'
0027
(
0028
)
0029
*
002A
+
002B
,
002C
-
002D
.
002E
/
002F
(1)
3_
0
0030
1
0031
2
0032
3
0033
4
0034
5
0035
6
0036
7
0037
8
0038
9
0039
:
003A
;
003B
<
003C
=
003D
>
003E
?
003F
(1)
4_
@
0040

0041
B
0042
C
0043
D
0044
E
0045
F
0046
G
0047
H
0048
I
0049
J
004A
K
004B
L
004C
M
004D
N
004E
O
004F
(1)
5_
P
0050
P
0051
R
0052
S
0053
T
0054
U
0055
V
0056
W
0057
X
0058
Tak
0059
Z
005A
[
005B
\
005C
]
005D
^
005E
_
005F
(1)
6_
`
0060

0061
b
0062
c
0063
d
0064
e
0065
f
0066
g
0067
h
0068
I
0069
j
006A
k
006B
L
006C
m
006D
n
006E
o
006F
(1)
7_
p
0070
q
0071
R
0072
s
0073
t
0.074
U
0075
v
0076
w
0077
x
0078
y
0079
z
007A
{
007B
|
007C
}
007D
~
007E
DEL
007F

8_

+00

+01

+02

+03

+04

+05

+06

+07

+08

+09

+0A

+0B

+0C

+0D

+0E

+0F

9_

+10

+11

+12

+13

+14

+15

+16

+17

+18

+19

+1A

+1B

+1C

+1D

+1E

+1F

A_

+20

+21

+22

+23

+24

+25

+26

+27

+28

+29

+2A

+2B

+2C

+2D

+2E

+2F

B_

+30

+31

+32

+33

+34

+35

+36

+37

+38

+39

+3A

+3B

+3C

+3D

+3E

+3F
(2)
C_
2
0000
2
0040
łacina
0080
łaciński
00C0
łacina
0100
łacina
0140
łaciński
0180
łaciński
01C0
łacina
0200
IPA
0240
IPA
0280
IPA
02C0
akcenty
0300
akcenty
0340
grecki
0380
grecki
03C0
(2)
D_
Cyryl
0400
Cyryl
0440
Cyryl
0480
Cyryl
04C0
Cyryl
0500
Armenii
0540
hebrajski
0580
hebrajski
05C0
arabski
0600
arabski
0640
arabski
0680
arabski
06C0
syryjski
0700
arabski
0740
Taana
0780
NKo
07C0
(3)
E_
Indyjski
0800
Różne
1000
Symbol
2000
Kana
3000
CJK
4000
CJK
5000
CJK
6000
CJK
7000
CJK
8000
CJK
9000
Azjatycka
A000
Hangul
B000
Hangul
C000
Hangul
D000
PUA
E000
PUA
F000
(4)
F_
SMP…
10000
񀀀
40000
򀀀
80000
SSP…
C0000
SPUA-B
100000
4
140000
4
180000
4
1C0000
5
200000
5
1000000
5
2000000
5
3000000
6
4000000
6
40000000

  Niebieskie komórki to 7-bitowe (jednobajtowe) sekwencje. Nie może następować po nich bajt kontynuacji.

  Pomarańczowe komórki z dużą kropką to bajt kontynuacji. Liczba szesnastkowa pokazana po symbolu + to wartość dodanych przez nich 6 bitów. Ten znak nigdy nie występuje jako pierwszy bajt sekwencji wielobajtowej.

  Białe komórki są wiodącymi bajtami dla sekwencji wielu bajtów, o długości pokazanej przy lewej krawędzi wiersza. Tekst pokazuje bloki Unicode zakodowane przez sekwencje zaczynające się od tego bajtu, a szesnastkowy punkt kodu pokazany w komórce to najniższa wartość znaku zakodowana przy użyciu tego bajtu wiodącego.

  Czerwone krwinki nigdy nie mogą pojawiać się w prawidłowej sekwencji UTF-8. Pierwsze dwie czerwone komórki ( C0 i C1 ) mogą być użyte tylko do 2-bajtowego kodowania 7-bitowego znaku ASCII, który powinien być zakodowany w 1 bajcie; jak opisano poniżej, takie „przedłużone” sekwencje są niedozwolone. Aby zrozumieć, dlaczego tak się dzieje, rozważ znak 128, szesnastkowy 80 , binarny 1000 0000 . Aby zakodować go jako 2 znaki, sześć młodszych bitów jest przechowywanych w drugim znaku jako 128 jako 10 000000 , ale dwa górne bity są przechowywane w pierwszym znaku jako 110 00010 , co daje minimalny pierwszy znak C2. Czerwone komórki w wierszu F_ ( F5 do FD ) wskazują wiodące bajty sekwencji 4-bajtowych lub dłuższych, które nie mogą być prawidłowe, ponieważ zakodowałyby punkty kodowe większe niż limit U + 10FFFF Unicode (limit wynikający z maksymalnego punktu kodu kodowane w UTF-16 ). FE i FF nie pasują do żadnego dozwolonego wzorca znaków i dlatego nie są prawidłowymi bajtami początkowymi.

  Różowe komórki są wiodącymi bajtami dla sekwencji wielu bajtów, z których niektóre, ale nie wszystkie, możliwe sekwencje kontynuacji są prawidłowe. E0 i F0 mogą rozpocząć kodowanie zbyt długie, w tym przypadku pokazany jest najniższy punkt kodowy nie zakodowany zbyt długo. F4 może uruchomić punkty kodowe większe niż U+10FFFF, które są nieprawidłowe. ED może rozpocząć kodowanie punktu kodowego z zakresu U+D800–U+DFFF; są one nieważne, ponieważ są zarezerwowane dla połówek zastępczych UTF-16 .

Przedłużone kodowania

W zasadzie możliwe byłoby zawyżenie liczby bajtów w kodowaniu poprzez dopełnienie punktu kodu wiodącymi zerami. Zakodować znak Euro € z powyższego przykładu w czterech bajtów zamiast trzech, może być wzmocniony z czołowymi 0s aż do uzyskania 21 bitów - 000 000010 000010 101100 , a kodowany jako 11110 000 10 000010 10 000010 10 101100 (lub F0 82 82 AC w systemie szesnastkowym). Nazywa się to zbyt długim kodowaniem .

Standard określa, że ​​prawidłowe kodowanie punktu kodowego wykorzystuje tylko minimalną liczbę bajtów wymaganą do przechowywania znaczących bitów punktu kodowego. Dłuższe kodowania są nazywane overlong i nie są prawidłowymi reprezentacjami punktu kodowego UTF-8. Ta reguła utrzymuje zgodność jeden do jednego między punktami kodowymi i ich prawidłowymi kodowaniami, dzięki czemu istnieje unikatowe prawidłowe kodowanie dla każdego punktu kodowego. Gwarantuje to, że porównania i wyszukiwania ciągów są dobrze zdefiniowane.

Nieprawidłowe sekwencje i obsługa błędów

Nie wszystkie sekwencje bajtów są poprawne w UTF-8. Dekoder UTF-8 powinien być przygotowany na:

  • nieprawidłowe bajty
  • nieoczekiwany bajt kontynuacji
  • bajt bez kontynuacji przed końcem znaku
  • ciąg kończący się przed końcem znaku (co może się zdarzyć przy prostym skróceniu ciągu)
  • zbyt długie kodowanie
  • sekwencja, która dekoduje do nieprawidłowego punktu kodowego

Wiele z pierwszych dekoderów UTF-8 dekodowało je, ignorując nieprawidłowe bity i akceptując zbyt długie wyniki. Starannie spreparowany nieprawidłowy kod UTF-8 może spowodować, że będą pomijać lub tworzyć znaki ASCII, takie jak NUL, ukośnik lub cudzysłowy. Nieprawidłowy kod UTF-8 został użyty do obejścia weryfikacji bezpieczeństwa w głośnych produktach, takich jak serwer WWW Microsoft IIS i kontener serwletów Apache Tomcat. RFC 3629 stwierdza „Implementacje algorytmu dekodowania MUSZĄ chronić przed dekodowaniem nieprawidłowych sekwencji”. Standard Unicode wymaga od dekoderów „...traktowania źle sformułowanej sekwencji jednostek kodu jako warunku błędu. Gwarantuje to, że nie zinterpretuje ani nie wyemituje źle sformułowanej sekwencji jednostek kodu”.

Od RFC 3629 (listopad 2003), wysokie i niskie połówki zastępcze używane przez UTF-16 (U+D800 do U+DFFF) oraz punkty kodowe niekodowane przez UTF-16 (te po U+10FFFF) nie są legalnymi wartościami Unicode, a ich kodowanie UTF-8 musi być traktowane jako nieprawidłowa sekwencja bajtów. Brak dekodowania niesparowanych połówek zastępczych uniemożliwia przechowywanie nieprawidłowego UTF-16 (takiego jak nazwy plików Windows lub UTF-16, który został podzielony między zastępcze) jako UTF-8, podczas gdy jest to możliwe w przypadku WTF-8 .

Niektóre implementacje dekoderów zgłaszają wyjątki dotyczące błędów. Ma to tę wadę, że może zmienić nieszkodliwe błędy (takie jak błąd „brak takiego pliku”) w odmowę usługi . Na przykład wczesne wersje Pythona 3.0 kończyłyby się natychmiast, jeśli wiersz poleceń lub zmienne środowiskowe zawierały nieprawidłowy kod UTF-8. Alternatywną praktyką jest zastępowanie błędów znakiem zastępczym. Od czasu Unicode 6 (październik 2010) standard (rozdział 3) zaleca „najlepszą praktykę”, w której błąd kończy się w momencie napotkania niedozwolonego bajtu. W tych dekoderach E1,A0,C0 to dwa błędy (2 bajty w pierwszym). Oznacza to, że błąd ma długość nie większą niż trzy bajty i nigdy nie zawiera początku prawidłowego znaku, a ponadto istnieje 21 952 różnych możliwych błędów. Norma zaleca również zastąpienie każdego błędu znakiem zastępczym „ ” (U+FFFD).

Oznaczenie kolejności bajtów

Jeśli znak kolejności bajtów UTF-16 Unicode (BOM, U+FEFF) znajduje się na początku pliku UTF-8, pierwsze trzy bajty będą 0xEF , 0xBB , 0xBF .

Standard Unicode nie wymaga ani nie zaleca używania BOM dla UTF-8, ale ostrzega, że ​​może wystąpić na początku pliku transkodowanego z innego kodowania. Chociaż tekst ASCII zakodowany przy użyciu UTF-8 jest wstecznie zgodny z ASCII, nie jest to prawdą, gdy zalecenia standardu Unicode są ignorowane i dodawany jest BOM. BOM może pomylić oprogramowanie, które nie jest na to przygotowane, ale w inny sposób akceptuje UTF-8, np. języki programowania, które zezwalają na bajty inne niż ASCII w literałach ciągu, ale nie na początku pliku. Niemniej jednak istniało i nadal istnieje oprogramowanie, które zawsze wstawia BOM podczas pisania UTF-8 i odmawia poprawnej interpretacji UTF-8, chyba że pierwszym znakiem jest BOM (lub plik zawiera tylko ASCII).

Niektóre języki programowania i formaty plików mają swój własny sposób oznaczania użycia kodowania, takiego jak UTF-8 w kodzie źródłowym. Przykłady obejmują HTML <meta charset="UTF-8"/> i Python 2.7 # coding: utf-8

Przyjęcie

Korzystanie z głównych kodowań w sieci w latach 2001-2012, jak zarejestrował Google, przy czym UTF-8 wyprzedził wszystkie inne w 2008 roku i ponad 60% sieci w 2012 roku (od tego czasu zbliża się do 100%). Liczba ASCII -only zawiera wszystkie strony internetowe zawierające tylko znaki ASCII, niezależnie od zadeklarowanego nagłówka.

UTF-8 to zalecenie WHATWG dla specyfikacji HTML i DOM , a Internet Mail Consortium zaleca, aby wszystkie programy pocztowe były w stanie wyświetlać i tworzyć pocztę przy użyciu UTF-8. World Wide Web Consortium zaleca UTF-8 jako domyślnego kodowania w formacie XML i HTML (a nie tylko za pomocą UTF-8, również podając je w metadanych), „nawet wtedy, gdy wszystkie znaki są w ASCII zakresie .. Korzystanie non-UTF- 8 kodowań może dać nieoczekiwane rezultaty". Wiele innych standardów obsługuje tylko UTF-8, np. wymaga tego otwarta wymiana JSON .

UTF-8 jest najpopularniejszym kodowaniem w sieci WWW od 2008 roku. W październiku 2021 r. UTF-8 stanowi średnio 97,3% wszystkich stron internetowych; i 988 z 1000 najwyżej ocenianych stron internetowych. UTF-8 zawiera ASCII jako podzbiór; prawie żadna strona internetowa nie deklaruje używania tylko ASCII. Kilka języków ma 100,0% użycia UTF-8.

W przypadku lokalnych plików tekstowych użycie UTF-8 jest mniejsze, a wiele starszych kodowań jednobajtowych (i wielobajtowych CJK ) pozostaje w użyciu. Główną przyczyną są edytory, które nie wyświetlają ani nie zapisują UTF-8, chyba że pierwszy znak w pliku jest znacznikiem kolejności bajtów (BOM), co uniemożliwia innym oprogramowaniu używanie UTF-8 bez przepisania, aby zignorować znacznik kolejności bajtów na wejściu i dodaj go na wyjściu. Ostatnio nastąpiła pewna poprawa, Notatnik w systemie Windows 10 domyślnie zapisuje UTF-8 bez BOM, a niektóre pliki systemowe w systemie Windows 11 wymagają UTF-8, a prawie wszystkie pliki w systemach MacOS i Linux muszą być w UTF-8 (bez zestawienia komponentów). Java , ze swoim interfejsem API NIO, domyślnie odczytuje i zapisuje pliki UTF-8 i zamierza to robić dla wszystkich innych interfejsów API plików. Działa już dla wszystkich interfejsów API na większości platform, z wyjątkiem Windows . „Wybór UTF-8 dotyczy tylko standardowych interfejsów API Javy, a nie języka Java, który nadal będzie używał UTF-16”. Wiele innych języków programowania domyślnie używa UTF-8 dla I/O; lub planujesz migrację do UTF-8, na przykład Pythona, który przygotowuje się do „zmiany domyślnego kodowania na UTF-8 [ponieważ stało się] de facto standardowym kodowaniem tekstu”. Większość baz danych obsługuje UTF-8 (czasami jedyna opcja, jak w przypadku niektórych formatów plików), w tym Microsoft od SQL Server 2019, co skutkuje 35% wzrostem prędkości i „prawie 50% zmniejszeniem wymagań dotyczących pamięci masowej”.

Wewnętrznie wykorzystanie oprogramowania jest niższe, z użyciem UTF-16 lub UCS-2 , szczególnie w systemie Windows, ale także przez JavaScript , Python , Qt i wiele innych wieloplatformowych bibliotek oprogramowania. Głównym tego powodem jest kompatybilność z Windows API , chociaż przekonanie, że bezpośrednie indeksowanie BMP poprawia szybkość, również było czynnikiem. Nowsze oprogramowanie zaczęło używać UTF-8: domyślnym prymitywem łańcuchowym używanym w Go , Julia , Rust , Swift 5 i PyPy jest UTF-8, przyszła wersja Pythona zamierza przechowywać łańcuchy jako UTF-8, a nowoczesne wersje z Microsoft Visual Studio UTF-8 wewnętrznie (jednak nadal wymagają przełącznika wiersza polecenia do odczytu lub zapisu UTF-8). UTF-8 to „jedyne kodowanie tekstu, które ma być obsługiwane przez standard C++”, począwszy od C++20 . Od maja 2019 r. firma Microsoft zmieniła kurs obsługi tylko UTF-16 dla Windows API, zapewniając możliwość ustawienia UTF-8 jako „strony kodowej” dla wielobajtowego API (wcześniej było to niemożliwe), a teraz Microsoft zaleca (programistom) używanie UTF-8 dla aplikacji Universal Windows Platform (UWP), przy jednoczesnym utrzymaniu starszego interfejsu „Unicode” (co oznacza UTF-16).

Historia

Międzynarodowa Organizacja Normalizacyjna (ISO) określone komponować uniwersalny zestaw znaków multi-byte w roku 1989. W projekcie normy ISO 10646 zawierał zakaz wymagany załącznik o nazwie UTF-1, który dostarczył bajt strumienia kodowania swoich 32-bitowych punktów kodowych . To kodowanie nie było satysfakcjonujące ze względu na wydajność, między innymi problemami, a największym problemem było prawdopodobnie to, że nie miało wyraźnego rozdziału między ASCII i nie-ASCII: nowe narzędzia UTF-1 byłyby kompatybilne wstecz z tekstem zakodowanym w ASCII, ale Tekst zakodowany w UTF-1 może zmylić istniejący kod oczekujący ASCII (lub rozszerzonego ASCII ), ponieważ może zawierać bajty kontynuacji z zakresu 0x21–0x7E, które oznaczały coś innego w ASCII, np. 0x2F dla „/”, separatora katalogów ścieżki uniksowej , a ten przykład znajduje odzwierciedlenie w nazwie i tekście wprowadzającym do zastąpienia. Poniższa tabela została zaczerpnięta z opisu tekstowego w załączniku.

UTF-1
Liczba
bajtów
Pierwszy
punkt kodowy
Ostatni
punkt kodowy
Bajt 1 Bajt 2 Bajt 3 Bajt 4 Bajt 5
1 U+0000 U+009F 00–9F
2 U+00A0 U+00FF A0 A0–FF
2 U+0100 U+4015 A1–F5 21-7E, A0-FF
3 U+4016 U+38E2D F6–FB 21-7E, A0-FF 21-7E, A0-FF
5 U+38E2E U+7FFFFFFFF FC–FF 21-7E, A0-FF 21-7E, A0-FF 21-7E, A0-FF 21-7E, A0-FF

W lipcu 1992 r. komitet X/Open XoJIG szukał lepszego kodowania. Dave Prosser z Unix System Laboratories przedstawił propozycję takiego, które miałoby szybsze właściwości implementacyjne i wprowadził ulepszenie polegające na tym, że 7-bitowe znaki ASCII będą reprezentować tylko same siebie; wszystkie sekwencje wielobajtowe zawierałyby tylko bajty, w których ustawiono wysoki bit. Nazwa File System Safe UCS Transformation Format (FSS-UTF) i większość tekstu tej propozycji zostały później zachowane w ostatecznej specyfikacji.

FSS-UTF

Propozycja FSS-UTF (1992)
Liczba
bajtów
Pierwszy
punkt kodowy
Ostatni
punkt kodowy
Bajt 1 Bajt 2 Bajt 3 Bajt 4 Bajt 5
1 U+0000 U+007F 0xxxxxxx
2 U+0080 U+207F 10xxxxxx 1xxxxxxx
3 U+2080 U+8207F 110xxxxx 1xxxxxxx 1xxxxxxx
4 U+82080 U+208207F 1110xxxx 1xxxxxxx 1xxxxxxx 1xxxxxxx
5 U+2082080 U+7FFFFFFFF 11110xxx 1xxxxxxx 1xxxxxxx 1xxxxxxx 1xxxxxxx

W sierpniu 1992 r. propozycja ta została rozesłana przez przedstawiciela IBM X/Open do zainteresowanych stron. Modyfikacja przez Kena Thompsona z Plan 9 systemu operacyjnego grupy w Bell Labs sprawiły, że nieco mniej wydajne niż nieco poprzedniej propozycji, ale co najważniejsze pozwoliło mu być samosynchronizujące , pozwalając czytnik rozpocząć w dowolnym miejscu i natychmiast wykryć bajt granice sekwencji. Zrezygnowano również ze stosowania stronniczości i zamiast tego dodano zasadę, że dozwolone jest tylko najkrótsze możliwe kodowanie; dodatkowa utrata zwartości jest stosunkowo niewielka, ale czytelnicy muszą teraz zwracać uwagę na nieprawidłowe kodowanie, aby uniknąć niezawodności, a zwłaszcza problemów z bezpieczeństwem. Projekt Thompsona został zarysowany 2 września 1992 roku na podkładce w restauracji w New Jersey z Robem Pike'em . W następnych dniach Pike i Thompson wdrożyli go i zaktualizowali Plan 9, aby używać go przez cały czas, a następnie przekazali swój sukces z powrotem do X/Open, który zaakceptował go jako specyfikację FSS-UTF.

FSS-UTF (1992) / UTF-8 (1993)
Liczba
bajtów
Pierwszy
punkt kodowy
Ostatni
punkt kodowy
Bajt 1 Bajt 2 Bajt 3 Bajt 4 Bajt 5 Bajt 6
1 U+0000 U+007F 0xxxxxxx
2 U+0080 U+07FF 110xxxxx 10xxxxxx
3 U+0800 U+FFFF 1110xxxx 10xxxxxx 10xxxxxx
4 U+10000 U+1FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
5 U+200000 U+3FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
6 U+4000000 U+7FFFFFFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

UTF-8 został po raz pierwszy oficjalnie zaprezentowany na konferencji USENIX w San Diego w dniach 25-29 stycznia 1993 roku. Grupa Robocza ds. Inżynierii Internetu przyjęła UTF-8 w swojej polityce dotyczącej zestawów znaków i języków w RFC 2277 ( BCP 18) dla przyszłego Internetu Standardy działają, zastępując zestawy znaków jednobajtowych, takie jak Latin-1 w starszych dokumentach RFC.

W listopadzie 2003 r. kod UTF-8 został ograniczony przez RFC  3629, aby dopasować go do ograniczeń kodowania znaków UTF-16 : wyraźnie zabraniając punktów kodowych odpowiadających znakom zastępczym o wysokiej i niskiej wartości, usuwając więcej niż 3% sekwencji trzybajtowych i kończąc przy U+10FFFF usunięto ponad 48% sekwencji czterobajtowych i wszystkie sekwencje pięcio- i sześciobajtowe.

Normy

Istnieje kilka aktualnych definicji UTF-8 w różnych dokumentach normatywnych:

  • RFC  3629 / STD 63 (2003), który ustanawia UTF-8 jako standardowy element protokołu internetowego
  • RFC  5198 definiuje UTF-8 NFC dla wymiany sieci (2008)
  • ISO/IEC 10646:2014 §9.1 (2014)
  • Standard Unicode, wersja 11.0 (2018)

Zastępują one definicje podane w następujących przestarzałych pracach:

  • Standard Unicode, wersja 2.0 , dodatek A (1996)
  • ISO/IEC 10646-1:1993 Poprawka 2 / Załącznik R (1996)
  • RFC  2044 (1996)
  • RFC  2279 (1998)
  • Standard Unicode, wersja 3.0 , §2.3 (2000) plus sprostowanie nr 1: Najkrótsza forma UTF-8 (2000)
  • Załącznik nr 27 do standardu Unicode: Unicode 3.1 (2001)
  • Standard Unicode, wersja 5.0 (2006)
  • Standard Unicode, wersja 6.0 (2010)

Wszystkie są takie same w swojej ogólnej mechanice, z głównymi różnicami w kwestiach, takich jak dozwolony zakres wartości punktów kodowych i bezpieczna obsługa nieprawidłowych danych wejściowych.

Porównanie z innymi kodowaniami

Oto niektóre z ważnych cech tego kodowania:

  • Kompatybilność wsteczna: kompatybilność wsteczna z ASCII i ogromna ilość oprogramowania zaprojektowanego do przetwarzania tekstu zakodowanego w ASCII były główną siłą napędową projektu UTF-8. W UTF-8 pojedyncze bajty z wartościami z zakresu od 0 do 127 mapują bezpośrednio na punkty kodowe Unicode w zakresie ASCII. Pojedyncze bajty z tego zakresu reprezentują znaki, tak jak w ASCII. Co więcej, 7-bitowe bajty (bajty, w których najbardziej znaczący bit to 0) nigdy nie pojawiają się w sekwencji wielobajtowej i żadna ważna sekwencja wielobajtowa nie jest dekodowana do punktu kodowego ASCII. Sekwencja 7-bitowych bajtów jest zarówno poprawnym ASCII, jak i poprawnym UTF-8, i przy każdej z interpretacji reprezentuje tę samą sekwencję znaków. Dlatego 7-bitowe bajty w strumieniu UTF-8 reprezentują wszystkie i tylko znaki ASCII w strumieniu. W związku z tym wiele procesorów tekstu, parserów, protokołów, formatów plików, programów do wyświetlania tekstu itp., które używają znaków ASCII do formatowania i sterowania, będzie nadal działać zgodnie z przeznaczeniem, traktując strumień bajtów UTF-8 jako sekwencję pojedynczych znaków. znaki bajtowe, bez dekodowania sekwencji wielobajtowych. Znaki ASCII, na których następuje przetwarzanie, takie jak znaki interpunkcyjne, odstępy i znaki sterujące, nigdy nie będą kodowane jako sekwencje wielobajtowe. Dlatego też takie procesory mogą po prostu ignorować lub przekazywać sekwencje wielobajtowe bez ich dekodowania. Na przykład białe znaki ASCII mogą być używane do tokenizacji strumienia UTF-8 na słowa; Do podzielenia strumienia UTF-8 na linie można użyć wysuwu wiersza ASCII; i znaki ASCII NUL mogą być używane do dzielenia danych zakodowanych w UTF-8 na łańcuchy zakończone znakiem NUL. Podobnie wiele ciągów formatujących używanych przez funkcje biblioteczne, takie jak „printf”, będzie poprawnie obsługiwać argumenty wejściowe zakodowane w UTF-8.
  • Powrót i automatyczne wykrywanie: tylko mały podzbiór możliwych ciągów bajtów jest prawidłowym ciągiem UTF-8: bajty C0, C1 i F5 do FF nie mogą się pojawić, a bajty z ustawionym wysokim bitem muszą być parami i inne wymagania . Jest bardzo mało prawdopodobne, aby czytelny tekst w jakimkolwiek rozszerzonym ASCII był poprawny w UTF-8. Część popularności UTF-8 wynika z tego, że zapewnia on również dla nich formę kompatybilności wstecznej. Procesor UTF-8, który błędnie odbiera rozszerzone ASCII jako dane wejściowe, może w ten sposób „automatycznie wykryć” to z bardzo wysoką niezawodnością. Błędy zastępcze będą fałszywie ujemne, a te będą rzadkie. Co więcej, w wielu aplikacjach, takich jak wyświetlanie tekstu, konsekwencje nieprawidłowego powrotu są zwykle niewielkie. Strumień UTF-8 może po prostu zawierać błędy, co powoduje, że schemat automatycznego wykrywania generuje fałszywe alarmy; ale automatyczne wykrywanie jest skuteczne w większości przypadków, zwłaszcza w przypadku dłuższych tekstów, i jest szeroko stosowane. Działa również w celu „powrotu” lub zastąpienia 8-bitowych bajtów przy użyciu odpowiedniego punktu kodowego dla starszego kodowania tylko w przypadku wykrycia błędów w UTF-8, umożliwiając odzyskanie, nawet jeśli UTF-8 i starsze kodowanie są połączone w tym samym plik.
  • Kod prefiksu : Pierwszy bajt wskazuje liczbę bajtów w sekwencji. Odczyt ze strumienia może natychmiast zdekodować każdą pojedynczą w pełni odebraną sekwencję, bez konieczności oczekiwania na pierwszy bajt następnej sekwencji lub wskazanie końca strumienia. Długość sekwencji wielobajtowych jest łatwo określana przez ludzi, ponieważ jest to po prostu liczba jedynek wyższego rzędu w bajcie wiodącym. Nieprawidłowy znak nie zostanie zdekodowany, jeśli strumień zakończy się w połowie sekwencji.
  • Samosynchronizacja : bajty wiodące i bajty kontynuacji nie współdzielą wartości (bajty kontynuacji zaczynają się od bitów 10, podczas gdy bajty pojedyncze zaczynają się od 0, a dłuższe bajty wiodące zaczynają się od 11 ). Oznacza to, że wyszukiwanie nie znajdzie przypadkowo sekwencji jednego znaku rozpoczynającej się w środku innego znaku. Oznacza to również, że początek znaku można znaleźć z losowej pozycji, wykonując kopię zapasową co najwyżej 3 bajtów, aby znaleźć bajt wiodący. Nieprawidłowy znak nie zostanie zdekodowany, jeśli strumień rozpocznie się w połowie sekwencji, a krótsza sekwencja nigdy nie pojawi się w dłuższej.
  • Kolejność sortowania: Wybrane wartości wiodących bajtów oznaczają, że listę ciągów UTF-8 można posortować w kolejności punktów kodowych, sortując odpowiednie sekwencje bajtów.

Jednobajtowe

  • UTF-8 może zakodować dowolny znak Unicode , unikając konieczności wymyślania i ustawiania „ strony kodowej ” lub w inny sposób wskazywać, jaki zestaw znaków jest używany, i umożliwiając jednoczesne wyjście w wielu skryptach. W przypadku wielu skryptów w użyciu było więcej niż jedno kodowanie jednobajtowe, więc nawet znajomość skryptu była niewystarczająca, aby wyświetlić go poprawnie.
  • Bajty 0xFE i 0xFF nie pojawiają się, więc prawidłowy strumień UTF-8 nigdy nie pasuje do znacznika kolejności bajtów UTF-16 i dlatego nie można go z nim pomylić. Brak 0xFF (0377) eliminuje również potrzebę ucieczki tego bajtu w Telnet (i połączeniach kontrolnych FTP).
  • Tekst zakodowany w UTF-8 jest większy niż wyspecjalizowane kodowanie jednobajtowe, z wyjątkiem zwykłych znaków ASCII. W przypadku skryptów, które używają 8-bitowych zestawów znaków ze znakami niełacińskimi zakodowanymi w górnej połowie (takich jak większość stron kodowych cyrylicy i alfabetu greckiego ), znaki w UTF-8 będą dwukrotnie większe. W przypadku niektórych skryptów, takich jak tajski i dewanagari (używany w różnych językach południowoazjatyckich), wielkość znaków potroi się. Istnieją nawet przykłady, w których pojedynczy bajt zamienia się w znak złożony w Unicode, a zatem jest sześć razy większy w UTF-8. Wywołało to sprzeciw w Indiach i innych krajach.
  • W UTF-8 (lub dowolnym innym kodowaniu o zmiennej długości) można podzielić lub obciąć łańcuch w środku znaku. Jeśli te dwie części nie zostaną ponownie dołączone później przed interpretacją jako znaki, może to wprowadzić nieprawidłową sekwencję zarówno na końcu poprzedniej sekcji, jak i na początku następnej, a niektóre dekodery nie zachowają tych bajtów i spowodują utratę danych. Ponieważ UTF-8 synchronizuje się samoczynnie, nigdy nie wprowadzi to innego poprawnego znaku, a także dość łatwo jest przenieść punkt obcięcia wstecz na początek znaku.
  • Jeśli wszystkie punkty kodowe mają ten sam rozmiar, pomiary ustalonej ich liczby są łatwe. Ze względu na dokumentację z czasów ASCII, gdzie „znak” jest używany jako synonim „bajtu”, jest to często uważane za ważne. Jednak mierząc pozycje ciągów za pomocą bajtów zamiast „znaków”, większość algorytmów można łatwo i skutecznie dostosować do UTF-8. Wyszukiwanie łańcucha w długim łańcuchu może na przykład odbywać się bajt po bajcie; właściwość samosynchronizacji zapobiega fałszywym alarmom.

Inne wielobajtowe

  • UTF-8 może kodować dowolny znak Unicode . Pliki w różnych skryptach mogą być wyświetlane poprawnie bez konieczności wybierania odpowiedniej strony kodowej lub czcionki. Na przykład chiński i arabski można zapisać w tym samym pliku bez specjalnych znaczników lub ręcznych ustawień określających kodowanie.
  • UTF-8 jest samosynchronizujący : granice znaków są łatwo identyfikowane poprzez skanowanie w poszukiwaniu dobrze zdefiniowanych wzorców bitowych w obu kierunkach. Jeśli bajty zostaną utracone z powodu błędu lub uszkodzenia , zawsze można znaleźć następny prawidłowy znak i wznowić przetwarzanie. Jeśli istnieje potrzeba skrócenia ciągu, aby zmieścił się w określonym polu, można łatwo znaleźć poprzedni poprawny znak. Wiele kodowań wielobajtowych, takich jak Shift JIS, jest znacznie trudniejszych do ponownej synchronizacji. Oznacza to również, że zorientowane bajtowo algorytmy wyszukiwania ciągów mogą być używane z UTF-8 (ponieważ znak jest tym samym, co „słowo” złożone z tylu bajtów), zoptymalizowane wersje wyszukiwania bajtów mogą być znacznie szybsze ze względu na sprzęt tabele obsługi i wyszukiwania, które mają tylko 256 wpisów. Samosynchronizacja wymaga jednak, aby bity były zarezerwowane dla tych znaczników w każdym bajcie, zwiększając rozmiar.
  • Wydajne kodowanie przy użyciu prostych operacji bitowych . UTF-8 nie wymaga wolniejszych operacji matematycznych, takich jak mnożenie lub dzielenie (w przeciwieństwie do Shift JIS , GB 2312 i innych kodowań).
  • UTF-8 zajmie więcej miejsca niż kodowanie wielobajtowe zaprojektowane dla konkretnego skryptu. Starsze kodowania wschodnioazjatyckie zwykle używają dwóch bajtów na znak, ale zajmują trzy bajty na znak w UTF-8.

UTF-16

  • Kodowanie bajtowe i UTF-8 są reprezentowane przez tablice bajtowe w programach i często nie trzeba nic robić z funkcją podczas konwersji kodu źródłowego z kodowania bajtowego na UTF-8. UTF-16 jest reprezentowany przez 16-bitowe tablice słów, a konwersja do UTF-16 przy zachowaniu kompatybilności z istniejącymi programami opartymi na ASCII (tak jak miało to miejsce w systemie Windows) wymaga każdego interfejsu API i struktury danych, która przyjmuje ciąg do zduplikowania, jeden wersja akceptująca ciągi bajtów i inna wersja akceptująca UTF-16. Jeśli zgodność z poprzednimi wersjami nie jest potrzebna, cała obsługa ciągów nadal musi zostać zmodyfikowana.
  • Tekst zakodowany w UTF-8 będzie mniejszy niż ten sam tekst zakodowany w UTF-16, jeśli jest więcej punktów kodowych poniżej U+0080 niż w zakresie U+0800..U+FFFF. Dotyczy to wszystkich współczesnych języków europejskich. Często dotyczy to nawet języków takich jak chiński, ze względu na dużą liczbę spacji, znaków nowej linii, cyfr i znaczników HTML w typowych plikach.
  • Większość komunikacji (np. HTML i IP) i przechowywania (np. dla Unixa) została zaprojektowana dla strumienia bajtów . Łańcuch UTF-16 musi używać pary bajtów dla każdej jednostki kodu:
    • Kolejność tych dwóch bajtów staje się problemem i musi być określona w protokole UTF-16, na przykład za pomocą znacznika kolejności bajtów .
    • Jeśli w UTF-16 brakuje nieparzystej liczby bajtów, cała reszta ciągu będzie tekstem bez znaczenia. Brakujące bajty w UTF-8 nadal pozwolą na dokładne odzyskanie tekstu, zaczynając od następnego znaku po brakujących bajtach.

Pochodne

Poniższe implementacje pokazują niewielkie różnice w stosunku do specyfikacji UTF-8. Są niezgodne ze specyfikacją UTF-8 i mogą zostać odrzucone przez aplikacje zgodne z UTF-8.

CESU-8

Raport Techniczny Unicode nr 26 przypisuje nazwę CESU-8 do niestandardowego wariantu UTF-8, w którym znaki Unicode w dodatkowych płaszczyznach są kodowane przy użyciu sześciu bajtów, a nie czterech bajtów wymaganych przez UTF-8. Kodowanie CESU-8 traktuje każdą połowę czterobajtowej pary zastępczej UTF-16 jako dwubajtowy znak UCS-2, dając dwa trzybajtowe znaki UTF-8, które razem reprezentują oryginalny znak uzupełniający. Znaki Unicode w Basic Multilingual Plane pojawiają się tak, jak normalnie w UTF-8. Raport został napisany, aby potwierdzić i sformalizować istnienie danych zakodowanych jako CESU-8, mimo że Konsorcjum Unicode zniechęca do ich używania, i zauważa, że ​​możliwą celową przyczyną kodowania CESU-8 jest zachowanie binarnego sortowania UTF-16.

Kodowanie CESU-8 może wynikać z konwersji danych UTF-16 ze znakami dodatkowymi na UTF-8 przy użyciu metod konwersji, które zakładają dane UCS-2, co oznacza, że ​​nie są świadome czterobajtowych znaków uzupełniających UTF-16. Jest to przede wszystkim problem w systemach operacyjnych, które wewnętrznie intensywnie używają UTF-16, takich jak Microsoft Windows .

W Oracle Database The UTF8zestaw znaków używa CESU-8 kodowania i jest przestarzała. Zestaw AL32UTF8znaków używa kodowania UTF-8 zgodnego ze standardami i jest preferowany.

CESU-8 jest zabronione do użytku w dokumentach HTML5 .

MySQL utf8mb3

W MySQL , utf8mb3zestaw znaków jest zdefiniowana jako UTF-8 zakodowane dane z maksymalnie trzech bajtów na znak, co oznacza tylko znaki Unicode w podstawowe Multilingual Plane (tj z UCS-2 ) są obsługiwane. Znaki Unicode w dodatkowych płaszczyznach nie są wyraźnie obsługiwane. utf8mb3jest przestarzały na rzecz utf8mb4zestawu znaków, który używa zgodnego ze standardami kodowania UTF-8. utf8jest aliasem dla utf8mb3, ale ma stać się aliasem utf8mb4w przyszłym wydaniu MySQL. Możliwe jest, choć nieobsługiwane, przechowywanie danych zakodowanych w CESU-8 w utf8mb3, przez obsługę danych UTF-16 z dodatkowymi znakami tak, jakby były to UCS-2.

Zmodyfikowany UTF-8

Zmodyfikowany kod UTF-8 (MUTF-8) pochodzi z języka programowania Java . W zmodyfikowanym UTF-8 znak null (U+0000) używa dwubajtowego, wydłużonego kodowania 110 00000 10 000000 (szesnastkowo C0 80 ), zamiast 00000000 (szesnastkowo 00 ). Zmodyfikowane ciągi znaków UTF-8 nigdy nie zawierają żadnych rzeczywistych bajtów null, ale mogą zawierać wszystkie punkty kodowe Unicode, w tym U + 0000, co pozwala na przetwarzanie takich ciągów (z dołączonym bajtem null) przez tradycyjne funkcje ciągów zakończone znakiem NULL . Wszystkie znane implementacje Zmodyfikowanego UTF-8 również traktują pary zastępcze jak w CESU-8 .

W normalnym użyciu język obsługuje standard UTF-8 podczas odczytywania i zapisywania ciągów za pomocą InputStreamReaderi OutputStreamWriter(jeśli jest to domyślny zestaw znaków platformy lub zgodnie z żądaniem programu). Jednak używa Zmodyfikowanego UTF-8 do serializacji obiektów między innymi aplikacjami DataInputi DataOutput, dla interfejsu Java Native oraz do osadzania ciągów stałych w plikach klas .

Format dex zdefiniowany przez Dalvik również używa tego samego zmodyfikowanego UTF-8 do reprezentowania wartości ciągu. Tcl używa również tego samego zmodyfikowanego UTF-8 co Java do wewnętrznej reprezentacji danych Unicode, ale używa ścisłego CESU-8 dla danych zewnętrznych.

WTF-8

W WTF-8 (Wobbly Transformation Format, 8-bitowy) dozwolone są niesparowane połówki zastępcze (od U+D800 do U+DFFF). Jest to konieczne do przechowywania prawdopodobnie niepoprawnego UTF-16, takiego jak nazwy plików Windows. Wiele systemów obsługujących UTF-8 działa w ten sposób bez uwzględniania innego kodowania, ponieważ jest to prostsze.

(Termin „WTF-8” był również używany żartobliwie w odniesieniu do błędnie podwójnie zakodowanego UTF-8, czasami z sugestią, że bajty CP1252 są jedynymi zakodowanymi.)

PEP 383

Wersja 3 języka programowania Python traktuje każdy bajt nieprawidłowego strumienia bajtów UTF-8 jako błąd (zobacz także zmiany w nowym trybie UTF-8 w Pythonie 3.7); daje to 128 różnych możliwych błędów. Rozszerzenia zostały stworzone, aby umożliwić bezstratną transformację dowolnej sekwencji bajtów, która jest uznawana za UTF-8 do UTF-16 lub UTF-32, poprzez translację 128 możliwych bajtów błędów na zarezerwowane punkty kodu i przekształcenie tych punktów kodu z powrotem w błąd bajtów do wyjścia UTF-8. Najpopularniejszym podejściem jest tłumaczenie kodów na U+DC80...U+DCFF, które są niskimi (końcowymi) wartościami zastępczymi, a zatem „nieprawidłowym” kodem UTF-16, używanym przez PEP 383 Pythona (lub „surogateescape”) zbliżać się. Inne kodowanie o nazwie MirBSD OPTU-8/16 konwertuje je na U+EF80...U+EFFF w obszarze prywatnego użytku . W każdym podejściu wartość bajtu jest zakodowana w ostatnich ośmiu bitach wyjściowego punktu kodu.

Te kodowania są bardzo przydatne, ponieważ pozwalają uniknąć konieczności radzenia sobie z „nieprawidłowymi” ciągami bajtów znacznie później, jeśli w ogóle, i pozwalają, aby tablice bajtów „text” i „data” były tym samym obiektem. Jeśli program chce używać wewnętrznie UTF-16, są one wymagane do zachowania i używania nazw plików, które mogą używać nieprawidłowego UTF-8; ponieważ API systemu plików Windows używa UTF-16, potrzeba obsługi nieprawidłowego UTF-8 jest tam mniejsza.

Aby kodowanie było odwracalne, standardowe kodowanie UTF-8 punktów kodowych używanych do błędnych bajtów należy uznać za nieprawidłowe. To sprawia, że ​​kodowanie jest niezgodne z WTF-8 lub CESU-8 (chociaż tylko dla 128 punktów kodowych). Podczas ponownego kodowania należy uważać na sekwencje punktów kodu błędu, które konwertują z powrotem na prawidłowy UTF-8, który może być używany przez złośliwe oprogramowanie do uzyskiwania nieoczekiwanych znaków w danych wyjściowych, chociaż nie może to generować znaków ASCII, więc jest uważane stosunkowo bezpieczne, ponieważ złośliwe sekwencje (takie jak cross-site scripting ) zwykle opierają się na znakach ASCII.

Zobacz też

Uwagi

Bibliografia

Zewnętrzne linki