Как приложения знают кодировку символов? - PullRequest
0 голосов
/ 28 ноября 2018

Допустим, у меня есть два файла, как показано ниже:

$ ll
total 8
-rw-rw-r--. 1 matias matias 6 Nov 27 20:25 ascii.txt
-rw-rw-r--. 1 matias matias 8 Nov 28 21:57 unicode.txt

Оба содержат одну строку текста, но во втором файле есть дополнительный символ, как показано здесь (греческая буква Sigma):

$ cat ascii.txt
   matias
$ cat unicode.txt
   matiasΣ

Если я пропущу их через команду file , это будет вывод:

$ file *
  ascii.txt:   ASCII text, with no line terminators
  unicode.txt: UTF-8 Unicode text, with no line terminators

Что кажется нормальным.Теперь, если я сделаю hexdump из файла, я получу это:

 $ hexdump -C ascii.txt
   00000000  6d 61 74 69 61 73                     |matias|
   00000006

 $ hexdump -C unicode.txt
   00000000  6d 61 74 69 61 73 ce a3               |matias..|
   00000008

Итак, мой вопрос, как приложение с именем cat знает, что последнеедва байта на самом деле один символ Unicode .Если я печатаю последние два байта по отдельности, я получаю:

 $ printf '%d' '0xce'
   206
 $ printf '%d' '0xa3'
   163

Что в расширенном ASCII:

 $ py3 -c 'print(chr(206))'
   Î
 $ py3 -c 'print(chr(163))'
   £

Моя логика неверна?Чего мне здесь не хватает?

Ответы [ 2 ]

0 голосов
/ 29 ноября 2018

Как приложения знают кодировку символов?

Либо:

  1. (Они предполагают - возможно, с помощью эвристики. Это не «знание».)
  2. Они точно вам скажут, какой использовать (через документацию, стандарт, соглашение и т. Д.).(На самом деле это тоже не «знание».)
  3. Они позволяют вам сказать им, какой вы используете.

Это ваш файл;Вы должны знать.

0 голосов
/ 29 ноября 2018

Инструменты командной строки работают с байтами - они получают байты и отправляют байты.Понятие символа - будь он представлен одним или несколькими байтами - является специфичной для задачи интерпретацией необработанных байтов.Когда вы вызываете cat для файла UTF-8, я предполагаю, что он просто перенаправляет байты, которые он читает, без заботы о символах.

Но ваш терминал, который должен отображать вывод cat, делает заботится о том, чтобы интерпретировать байты как символы и показывать один символ для последовательности байтов 206, 163. Из его конфигурации (locale env vars и т. д.) ваш терминал, очевидно, предполагает, что текстовый ввод-вывод происходит с UTF-8.Если это предположение нарушается (например, если команда отправляет байт 206 изолированно, что является недействительным UTF-8), вы увидите символы � или другой текстовый мусор.Поскольку UTF-8 был разработан для обеспечения обратной совместимости с ASCII, текстовые файлы ASCII можно обрабатывать так же, как файлы UTF-8 ( * UTF-8).

Хотя catвероятно, не заботятся о символах, многие другие команды делают, например.wc -m команда для подсчета символов (не байтов!) в текстовом файле.Все эти команды должны знать, как UTF-8 (или какова бы ни была ваша кодировка терминала) отображает байты в символы и наоборот.Например, когда вы print(chr(206)) в Python, он отправляет байты 195, 142 в STDOUT, потому что: (a) он выяснил, что ваш терминал ожидает UTF-8 и (b) символ «Î» (к которому кодовая точка Unicode206 соответствует) представлен этими двумя байтами в UTF-8.Наконец, терминал отображает «Î», поскольку он декодирует два байта в соответствующий символ.

...