Jaka jest różnica między kodowaniem a zestawem znaków?

151

Nie mam pewności co do kodowania tekstu i zestawu znaków. Z wielu powodów muszę się nauczyć rzeczy innych niż Unicode i UTF8 w mojej nadchodzącej pracy.

Znajduję słowo „charset” w nagłówkach e-maili, jak w „ISO-2022-JP”, ale nie ma takiego kodowania w edytorach tekstu. (Rozejrzałem się po różnych edytorach tekstu.)

Jaka jest różnica między kodowaniem tekstu a zestawem znaków? Byłbym wdzięczny, gdybyś mógł mi pokazać kilka przykładów użycia.

TK.
źródło

Odpowiedzi:

144

Gruntownie:

  1. charset to zestaw znaków, których możesz użyć
  2. kodowanie to sposób, w jaki te znaki są przechowywane w pamięci
Svetlozar Angelov
źródło
42
To prawda, ale w praktyce określenie „zestaw znaków” zwykle odnosi się zarówno do repertuaru znaków, jak i do schematu kodowania.
Alan Moore
@AlanMoore Rzeczywiście, prawie tak samo, jak ludzie mówią „liczba dziesiętna”, odnosząc się do dowolnej liczby z „separatorem dziesiętnym”. To nie jest poprawne, ale tak, powinieneś być świadomy, że niektórzy ludzie używają go w ten sposób.
bvdb
2
To nie jest dokładnie w porządku. Na przykład Unicode odnosi się do zestawu znaków, ale istnieje wiele możliwych kodowań (UTF-8, UTF-16, UTF-32).
rghome
84

Z każdym kodowaniem jest powiązany określony zestaw znaków, ale może istnieć więcej niż jedno kodowanie dla danego zestawu znaków. Zestaw znaków to po prostu to, na co wygląda, zestaw znaków. Istnieje wiele zestawów znaków, w tym wiele przeznaczonych dla określonych skryptów lub języków.

Jednak jesteśmy na dobrej drodze do przejścia na Unicode, który zawiera zestaw znaków, który może reprezentować prawie wszystkie skrypty świata. Jednak istnieje wiele kodowań dla Unicode. Kodowanie to sposób odwzorowania ciągu znaków na ciąg bajtów. Przykłady kodowania Unicode obejmują UTF-8 , UTF-16 BE i UTF-16 LE . Każdy z nich ma zalety dla określonych aplikacji lub architektur maszyn.

Matthew Flaschen
źródło
20
Zwróć uwagę, że javadoc błędnie używa „charset” zamiast „encoding”, na przykład w InputStreamReader czytamy „InputStreamReader jest pomostem między strumieniami bajtów a strumieniami znaków: odczytuje bajty i dekoduje je na znaki przy użyciu określonego zestawu znaków. używane mogą być określone przez nazwę lub podane bezpośrednio, albo domyślny zestaw znaków platformy może zostać zaakceptowany. " . Jednak mają na myśli „kodowanie”.
David Tonhofer
4
Dziękuję za wyjaśnienie. Unicode to zestaw znaków, a UTF-8 to jeden ze sposobów kodowania Unicode , a UTF-16 to inny sposób kodowania Unicode .
HongchaoZhang
47

Oprócz innych odpowiedzi myślę, że ten artykuł jest dobrą lekturą http://www.joelonsoftware.com/articles/Unicode.html

Artykuł zatytułowany jest „ Absolutne minimum każdy programista absolutnie, pozytywnie musi wiedzieć o Unicode i zestawach znaków (bez wymówek!) ”, Którego autorem jest Joel Spolsky . Esej ma ponad 10 lat, ale (niestety) jego treść jest nadal aktualna ...

mattanja
źródło
2
Wielkie dzięki za wprowadzenie artykułu. To jest dobre.
TK.
9
Tę odpowiedź można poprawić, podając krótkie wyjaśnienie, dlaczego powinienem przeczytać artykuł Joela.
james.garriss
@mattanja Podany przez Ciebie link jest naprawdę świetny. Dzięki za udostępnienie. Zagłosowano.
hagrawal
1
Chcę również zamieścić ten wspaniały artykuł, który jest swego rodzaju dodatkiem do artykułu Joela Spolsky'ego; kunststube.net/encoding
mkb
Nie zrozumiałem artykułu Joela podczas pierwszego czytania. Uważam raczej, że ten powerpoint jest znacznie jaśniejszy i bardziej szczegółowy: unicode.org/notes/tn23/Muller-Slides+Narr.pdf
johnsimer
27

Kodowanie znaków składa się z:

  1. Zestaw obsługiwanych znaków
  2. Odwzorowanie między znakami i liczbami całkowitymi („punkty kodowe”)
  3. Jak punkty kodowe są kodowane jako seria „jednostek kodu” (np. Jednostki 16-bitowe dla UTF-16)
  4. Jak jednostki kodu są kodowane w bajtach (np. Big-endian lub little-endian)

Krok # 1 sam w sobie jest „repertuarem znaków” lub abstrakcyjnym „zestawem znaków”, a # 1 + # 2 = „zakodowany zestaw znaków”.

Ale zanim Unicode stał się popularny i wszyscy (z wyjątkiem wschodnioazjatyckich) używali kodowania jednobajtowego, kroki # 3 i # 4 były trywialne (punkt kodowy = jednostka kodu = bajt). Dlatego starsze protokoły nie rozróżniały wyraźnie między „kodowaniem znaków” a „zakodowanym zestawem znaków”. Starsze protokoły są używane, charsetgdy naprawdę oznaczają kodowanie.

dan04
źródło
czy to dlatego możemy odczytać charset = 'utf-8' w tagu HTML META? ponieważ zostało to zdefiniowane dawno temu
Eildosa
26

Rzucając więcej światła osobom odwiedzającym odtąd, miejmy nadzieję, że będzie to pomocne.


Zestaw znaków

W każdym języku istnieją znaki, a zbiór tych znaków tworzy „zestaw znaków” tego języka. Gdy znak jest kodowany, przypisywany jest mu niepowtarzalny identyfikator lub numer nazywany punktem kodowym. W komputerze te punkty kodowe będą reprezentowane przez jeden lub więcej bajtów.

Przykłady zestawu znaków: ASCII (obejmuje wszystkie angielskie znaki), ISO / IEC 646, Unicode (obejmuje znaki ze wszystkich żywych języków na świecie)

Zakodowany zestaw znaków

Zakodowany zestaw znaków to zestaw, w którym każdemu znakowi przypisany jest unikalny numer. Ten unikalny numer nazywany jest „punktem kodowym”.
Zakodowane zestawy znaków są czasami nazywane stronami kodowymi.

Kodowanie

Kodowanie to mechanizm mapowania punktów kodowych z pewnymi bajtami, tak aby znak mógł być odczytywany i zapisywany jednolicie w różnych systemach przy użyciu tego samego schematu kodowania.

Przykłady kodowania: ASCII, schematy kodowania Unicode, takie jak UTF-8, UTF-16, UTF-32.

Opracowanie powyższych 3 koncepcji

  • Rozważ to - znak „क” w zestawie znaków Devanagari ma dziesiętny punkt kodowy 2325, który będzie reprezentowany przez dwa bajty ( 09 15) przy użyciu kodowania UTF-16
  • W schemacie kodowania „ISO-8859-1” „ü” (to nic innego jak znak w zestawie znaków łacińskich) jest reprezentowane jako wartość szesnastkowa, FCpodczas gdy w „UTF-8” jest reprezentowane jako, C3 BCaw UTF-16 jako FE FF 00 FC.
  • Różne schematy kodowania mogą wykorzystywać ten sam punkt kodowy do reprezentowania różnych znaków, na przykład w „ISO-8859-1” (zwanej również Latin1) dziesiętna wartość punktu kodowego dla litery „é” wynosi 233. Jednak w ISO 8859-5 , ten sam punkt kodowy reprezentuje znak cyrylicy „щ”.
  • Z drugiej strony, pojedynczy punkt kodowy w zestawie znaków Unicode może być faktycznie odwzorowany na różne sekwencje bajtów, w zależności od tego, które kodowanie zostało użyte w dokumencie. Znak Devanagari क, z punktem kodowym 2325 (czyli 915 w notacji szesnastkowej), będzie reprezentowany przez dwa bajty w przypadku kodowania UTF-16 ( 09 15), trzy bajty w przypadku UTF-8 ( E0 A4 95) lub cztery bajty w przypadku UTF-32 ( 00 00 09 15)
hagrawal
źródło
11

Zestaw znaków lub repertuar znaków to po prostu zestaw (nieuporządkowana kolekcja) znaków. Zakodowany zestaw znaków przypisuje liczbę całkowitą („punkt kodowy”) do każdego znaku w repertuarze. Kodowanie to sposób jednoznacznego przedstawiania punktów kodowych jako strumienia bajtów.

Jonathan Feinberg
źródło
To powinna być akceptowana odpowiedź. Wyraźnie definiuje trzy pojęcia: zestaw znaków, zestaw zakodowanych znaków i kodowanie.
Marcus Junius Brutus
6

Wygooglowałem to. http://en.wikipedia.org/wiki/Character_encoding

Różnica wydaje się być subtelna. Termin zestaw znaków w rzeczywistości nie dotyczy Unicode. Unicode przechodzi przez szereg abstrakcji. abstrakcyjne znaki -> punkty kodowe -> kodowanie punktów kodowych do bajtów.

Zestawy znaków faktycznie to pomijają i bezpośrednio przeskakują ze znaków na bajty. sekwencja bajtów <-> sekwencja znaków

Krótko mówiąc, kodowanie: punkty kodowe -> kodowanie bajtów: znaki -> bajty

Fakrudeen
źródło
5

Zestaw znaków to tylko zestaw; albo zawiera np. znak euro, albo go nie zawiera. To wszystko.

Kodowanie to bijektywne odwzorowanie z zestawu znaków na zbiór liczb całkowitych. Jeśli obsługuje znak Euro, musi przypisać określoną liczbę całkowitą do tego znaku i do żadnego innego.

Kilian Foth
źródło
Czy to musi być bijektywne?
Jörg W Mittag,
2
Cóż, kodowanie i dekodowanie powinno być deterministyczne, więc naprawdę nie może być niejednoznacznych mapowań. Przypuszczam, że możesz mieć nieciągłe zbiory liczb całkowitych jako kodomenę, ale to marnowałoby miejsce podczas przechowywania tekstu, a inżynierowie nienawidzą marnowania miejsca.
Kilian Foth
1
Starsze kodowanie znaków często nie jest bijektywne. Na przykład w IBM437 zarówno ß, jak i β są reprezentowane przez 0xE1.
dan04
3

Moim zdaniem zestaw znaków jest częścią kodowania (komponentem), kodowanie ma atrybut zestawu znaków, więc zestaw znaków może być używany w wielu kodowaniach. Na przykład unicode to zestaw znaków używany w kodowaniach takich jak UTF-8, UTF-16 i tak dalej. Zobacz ilustrację tutaj:Zobacz ilustrację tutaj

Znak w zestawie znaków nie oznacza typu znaku w świecie programowania, oznacza znak w świecie rzeczywistym, w języku angielskim może to być to samo, ale w innych językach nie, jak chiński, `` 我 '' jest nieodłącznym znakiem w zestawach znaków (UNICODE, GB [używany w GBK i GB2312]), „a” jest również znakiem w zestawach znaków (ASCII, ISO-8859 , UNICODE).

Eric Liu
źródło
1

Moim zdaniem słowo „charset” powinno ograniczać się do określenia parametru używanego w standardach HTTP, MIME i podobnych w celu określenia kodowania znaków (odwzorowania z serii znaków tekstowych na sekwencję bajtów) według nazwy. Na przykład: charset=utf-8.

Zdaję sobie jednak sprawę, że MySQL, Java i inne miejsca mogą używać słowa „zestaw znaków” na oznaczenie kodowania znaków.

Peter O.
źródło
1

Kodowanie to odwzorowanie między bajtami i znakami z zestawu znaków, dlatego pomocne będzie omówienie i zrozumienie różnicy między bajtami a znakami .

Pomyśl o bajtach jak o liczbach od 0 do 255, podczas gdy znaki to abstrakcyjne rzeczy, takie jak „a”, „1”, „$” i „Ę”. Zestaw wszystkich dostępnych znaków nazywany jest zestawem znaków .

Każdy znak ma sekwencję jednego lub więcej bajtów, które są używane do jego reprezentacji; jednak dokładna liczba i wartość bajtów zależy od zastosowanego kodowania i istnieje wiele różnych kodowań.

Większość kodowań opiera się na starym zestawie znaków i kodowaniu zwanym ASCII, które ma jeden bajt na znak (w rzeczywistości tylko 7 bitów) i zawiera 128 znaków, w tym wiele typowych znaków używanych w amerykańskim angielskim.

Na przykład tutaj jest 6 znaków w zestawie znaków ASCII, które są reprezentowane przez wartości od 60 do 65.

Extract of ASCII Table 60-65
╔══════╦══════════════╗
║ Byte ║  Character   ║
╠══════╬══════════════║
║  60  ║      <       ║
║  61  ║      =       ║
║  62  ║      >       ║
║  63  ║      ?       ║
║  64  ║      @       ║
║  65  ║      A       ║
╚══════╩══════════════╝

W pełnym zestawie ASCII najniższa używana wartość to zero, a najwyższa 127 (oba to ukryte znaki sterujące).

Jednak gdy zaczniesz potrzebować więcej znaków niż zapewnia podstawowy ASCII (na przykład litery z akcentami, symbole walut, symbole graficzne itp.), ASCII nie jest odpowiednie i potrzebujesz czegoś bardziej rozbudowanego. Potrzebujesz więcej znaków (inny zestaw znaków) i potrzebujesz innego kodowania, ponieważ 128 znaków nie wystarczy, aby zmieścić wszystkie znaki. Niektóre kodowania oferują jeden bajt (256 znaków) lub do sześciu bajtów.

Z biegiem czasu powstało wiele kodowań. W świecie Windows istnieje CP1252 lub ISO-8859-1, podczas gdy użytkownicy Linuksa wolą UTF-8. Java natywnie używa UTF-16.

Jedna sekwencja wartości bajtów dla znaku w jednym kodowaniu może oznaczać zupełnie inny znak w innym kodowaniu, a nawet może być nieprawidłowa.

Na przykład, w ISO 8859-1 , Â jest reprezentowany przez jeden bajt wartości 226, podczas gdy w UTF-8 to dwa bajty: 195, 162. Jednak w ISO 8859-1 , 195, 162byłyby dwie postacie, a, ¢ .

Kiedy komputery przechowują dane o znakach wewnętrznie lub przesyłają je do innego systemu, przechowują lub wysyłają bajty. Wyobraź sobie, że system otwierający plik lub odbierający wiadomość widzi bajty 195, 162. Skąd wie, jakie to są postacie?

Aby system mógł zinterpretować te bajty jako rzeczywiste znaki (i wyświetlić je lub przekonwertować na inne kodowanie), musi znać zastosowane kodowanie. Dlatego kodowanie pojawia się w nagłówkach XML lub można je określić w edytorze tekstu. Informuje system o mapowaniu między bajtami i znakami.

rghome
źródło