Ответ 1
Отчасти потому, что файловые системы ожидают, что NUL ('\ 0') байты прекратят имена файлов, поэтому UTF-16 не будет работать. Вам нужно будет изменить много кода, чтобы внести изменения.
Я знаю, что это принято, но почему? Существуют ли реальные технические причины, по которым любой другой способ был бы очень плохой идеей или он основывался только на истории кодирования и обратной совместимости? Кроме того, в чем опасность не использования UTF-8
, а какая-то другая кодировка (в первую очередь, UTF-16
)?
Изменить: взаимодействуя, я в основном имею в виду shell
и libc
.
Отчасти потому, что файловые системы ожидают, что NUL ('\ 0') байты прекратят имена файлов, поэтому UTF-16 не будет работать. Вам нужно будет изменить много кода, чтобы внести изменения.
Как упоминает jonathan-leffler, основная проблема - это нулевой символ ASCII. C традиционно ожидает, что строка будет нулевой. Таким образом, стандартные строковые функции C будут подавляться на любом символе UTF-16, содержащем байт, эквивалентный нулевому значению ASCII (0x00). Хотя вы можете программировать с широкой поддержкой символов, UTF-16 не является подходящим внешним кодированием Unicode в именах файлов, текстовых файлов, переменных окружения.
Кроме того, UTF-16 и UTF-32 имеют как среднюю, так и маломерную ориентацию. Чтобы справиться с этим, вам понадобятся внешние метаданные, такие как MIME-тип, или Byte Orientation Mark. Он отмечает,
Где UTF-8 используется прозрачно в 8-битные среды, использование спецификации будет препятствовать любому протоколу или формат файла, который Символы ASCII в начале, например, использование "#!" на начало сценариев оболочки Unix.
Предшественник UTF-16, который назывался UCS-2 и не поддерживал суррогатные пары, имел те же проблемы. UCS-2 следует избегать.
Я считаю, что в основном это совместимость с обратной совместимостью, которую UTF8 дает с ASCII.
Для ответа на вопрос "Опасности" вам нужно указать, что вы подразумеваете под "взаимодействием". Вы имеете в виду взаимодействие с оболочкой, с libc или с самим ядром?
Современные Unix используют UTF-8, но это не всегда так. На RHEL2 - которому всего несколько лет - по умолчанию
$ locale LANG=C LC_CTYPE="C" LC_NUMERIC="C" LC_TIME="C" LC_COLLATE="C" LC_MONETARY="C" LC_MESSAGES="C" LC_PAPER="C" LC_NAME="C" LC_ADDRESS="C" LC_TELEPHONE="C" LC_MEASUREMENT="C" LC_IDENTIFICATION="C" LC_ALL=Предполагается, что языковой стандарт C/POSIX будет 7-разрядным ASCII-совместимым кодированием.
Однако, как заявил Джонатан Леффлер, любая кодировка, которая допускает NUL байты в последовательности символов, не работает в Unix, так как системные API не являются языковыми; все строки считаются байтовыми последовательностями, завершаемыми символом\0.
Я считаю, что, когда Microsoft начала использовать двухбайтную кодировку, символы выше 0xffff не были назначены, поэтому использование двухбайтовой кодировки означало, что никто не должен был беспокоиться о том, что символы различной длины.
Теперь, когда есть символы за пределами этого диапазона, вам все равно придется иметь дело с символами разной длины, зачем кому-то использовать UTF-16? Я подозреваю, что Microsoft приняла бы другое решение, если бы сегодня планировала поддержку своих юникодов.
Да, это по соображениям совместимости. UTF-8 обратно сопоставляется с ASCII. Linux/Unix были основаны на ASCII, поэтому он просто сделал/имеет смысл.
Я думал, что 7-битный ASCII был в порядке.
Серьезно, Unicode является относительно новым в схеме вещей, а UTF-8 обратно совместим с ASCII и использует меньше места (половина ) для типичных файлов, поскольку он использует от 1 до 4 байтов на кодовую точку (символ), а UTF-16 использует либо 2, либо 4 байта на код точка (символ).
UTF-16 является предпочтительным для использования внутренней программы из-за более простой ширины. Его предшественник UCS-2 составлял ровно 2 байта для каждой кодовой точки.
Я думаю, потому что программы, ожидающие ввода ASCII, не смогут обрабатывать кодировки, такие как UTF-16. Для большинства символов (в диапазоне 0-255) эти программы будут видеть старший байт как NUL/0 char, который используется на многих языках и системах для обозначения конца строки. Этого не происходит в UTF-8, который был разработан, чтобы избежать встроенного NUL и быть агностиком байтового порядка.