Я читал в Википедии и наткнулся на следующее:
"Since ASCII bytes do not occur when encoding non-ASCII code points into UTF-8,
UTF-8 is safe to use within most programming and document languages that
interpret certain ASCII characters in a special way, such as "/" in filenames,
"\" in escape sequences, and "%" in printf."
Я не могу понять, как это могло бы стать проблемой, даже если бы это случилось. Если приложение, обрабатывающее байты, поддерживает utf-8, тогда это простая ситуация, и не будет никаких проблем, поскольку оно будет знать, как интерпретировать их в контексте других байтов-предшественников / преемников. А если этого не произойдет, то он не имеет с этим никаких дел, и тот факт, что он может натолкнуться на комбинацию битов, являющихся символом формата, подобным '\', не более вреден, чем уже обрабатывает его в первое место.
Возьмем, к примеру, PHP. PHP не имеет собственного понимания кодировок (здесь есть некоторые звездочки и сноски, но, скажем так, это не так). Он ищет определенный конкретный байты в исходном коде, который что-то для него значит, и в основном просто пропускает через все остальное, что не имеет для него особого значения. Например.:
$foo = "bar $baz 42";
Это вызывает интерполяцию строк; PHP попытается вставить в эту строку переменную $baz
. Это делается путем поиска байта 0x24
(ASCII «$») и следующего «не-словного» байта в строке, что приводит к нахождению имени переменной $baz
внутри строки. Все остальное в строке проходит как есть.
Вы можете сделать это на PHP:
echo "意味分からない";
Все, что PHP видит здесь, - это какой-то двоичный объект, который не представляет для него особого интереса. Он не поддерживает и не понимает этих персонажей, но и не пытается что-либо с ними сделать. Он просто передает двоичные данные как есть и, таким образом, выводит желаемое японское предложение.
Теперь, если бы мы написали это предложение в какой-нибудь кодировке, не безопасной для ASCII, например, в ISO-2022-JP-3, это было бы:
1b24 4230 554c 234a 2c24 2b24 6924 4a24 241b 2842
Вы заметите там байты 24
. Если бы вы могли создать действительный файл PHP, содержащий эти байты в двойных кавычках, PHP попытался бы интерпретировать эти байты 0x24
как $
и попытаться интерполировать там переменные.
$ cat /tmp/foo.php
<?php echo "B0UL#J,$+$i$J$$";
$ xxd /tmp/foo.php
00000000: 3c3f 7068 7020 6563 686f 2022 1b24 4230 <?php echo ".$B0
00000010: 554c 234a 2c24 2b24 6924 4a24 241b 2842 UL#J,$+$i$J$$.(B
00000020: 223b 0a ";.
$ php /tmp/foo.php
PHP Notice: Undefined variable: B0UL in /tmp/foo.php on line 1
PHP Notice: Undefined variable: i in /tmp/foo.php on line 1
PHP Notice: Undefined variable: J in /tmp/foo.php on line 1
Это - один из примеров ситуации, когда важна совместимость UTF-8 с ASCII.
Именно это делает UTF-8 «совместимым с ASCII».
... Перечитывая вопрос, вижу, что об этом там уже упоминалось :)
Я понимаю, как utf-8 безопасен для ascii, но я не могу представить себе контекст, в котором это может быть не так, то есть кодировка, которая понимает Unicode, включая Ascii, но не безопасна для Ascii. Скажем, utf-8 создает байты, подобные ascii, при кодировании других кодовых точек, отличных от ascii, тогда вполне естественно, что алгоритм декодирования обработки будет знать, как интерпретировать их в перспективе, а не путать их как отдельные ASCII. Если он генерирует октеты ASCII, должна быть какая-то логика, чтобы различать их и правильно интерпретировать ...
@Learnerer Как я пытался продемонстрировать, существуют наивные системы, которые ничего не декодировать. ищут определенные последовательности байтов и игнорируют все остальное. Им известны только ASCII или ASCII-совместимые кодировки, которые совсем не нужно «интерпретировать в перспективе». Это просто байты, и эти байты были определены богами много лет назад, и вам просто нужно искать байты, которые что-то значат для вас, и вы можете игнорировать все остальное. По крайней мере, так гласила мантра для этих систем.
@deceze Thx. Но, как я сказал в своем вопросе выше, если система не работает с не-ascii, тогда нам не нужно беспокоиться о том, что она неверно интерпретирует части кодировки как asciis, поскольку обработка такого текста в первую очередь является error, т.е. зачем заботиться об ошибке, возникающей поверх ошибки. Мое мнение: этот аргумент, который я прочитал, кажется мне, как будто он пытается продвинуть положительное качество в utf-8, когда это действительно естественная особенность, которую следует принимать как должное в кодировке, которая может обрабатывать ascii - отсюда и мое замешательство ... !
@Learnerer UTF-8, совместимый с ASCII, позволяет таким наивным системам «поддерживать Unicode», фактически не поддерживая Unicode. То есть вам не нужно переделывать всю систему, чтобы сделать ее полностью осведомленной о кодировании, ей просто нужно ничего не делать с байтами, которые ее не касаются. Да, в идеальном мире все должно происходить иначе, но без этой совместимости у нас, вероятно, не было бы такой широкой поддержки Unicode, как у нас.
Спасибо. ... и последнее: те объекты в кодировке utf-8, на которые вы ссылались, по-прежнему будут содержать подлинные (преднамеренные) символы ascii как часть юникода, поэтому тот факт, что utf-8 не создает эти байты ascii как часть других chars, не предотвращает появление этих символов в кодировке, и ситуация, которую вы продемонстрировали выше, все равно может возникнуть ..?
Я не уверен, что понимаю… !? Если у вас есть байт в UTF-8, который интерпретируется как «$», это потому, что вы хотели ввести там «$». Если вы сравните это с приведенным выше примером ISO-2022, там много «$», которые являются случайными. Вы не имели в виду, чтобы там были эти «$», но программа, которая ожидала ASCII, увидела эти случайные байты как «$». UTF-8 этого избегает. Программа, ожидающая ASCII, увидит «$» в UTF-8 только тогда, когда вы означало поместите туда «$».
Да, это то, что я имел в виду, преднамеренные символы ascii ... Однако теперь я думаю, что я стал яснее ... Спасибо.
Это очень интересно. Возможно, уместно отметить, что по определению все байты в последовательности UTF-8, кодирующей символ Unicode за пределами диапазона ASCII (0-127), полностью состоят из байтов, больших или равных 128, поэтому невозможно, чтобы случайные 24 появится где-нибудь еще в файле с кодировкой UTF-8.