Открытие файла в текстовом режиме может привести к потере данных в Python: почему?

#python #codec #8-bit #7-bit

#python #кодек #8-разрядный #7-разрядный

Вопрос:

В документации для codecs.open() упоминается, что

Файлы всегда открываются в двоичном режиме, даже если двоичный режим не был указан. Это сделано, чтобы избежать потери данных из-за кодировок, использующих 8-битные значения.

Как использование текстового режима для файла может привести к «потере данных»? Похоже, что открытие файла в текстовом режиме может сократить байты до 7 бит, но я не могу найти никаких упоминаний об этом в документации: текстовый режим описывается только как способ преобразования новых строк, без упоминания о некоторой потенциальной потере данных. Итак, на что codecs.open() ссылается документация?

PS: Хотя понятно, что автоматическое преобразование новой строки в зависящую от платформы кодировку новой строки требует некоторой осторожности, вопрос заключается в том, что конкретно касается 8-битных кодировок. Я бы предположил, что только некоторые кодировки совместимы с автоматическим преобразованием новой строки, независимо от того, являются ли они 8- или 7-разрядными кодировками. Итак, почему в codecs.open() документации выделены 8-битные кодировки?

Комментарии:

1. Я бы предположил, что преобразование новых строк может повлиять на данные в файле. Данные будут означать то же самое, но, например, r n может быть преобразован просто в n. Я действительно не уверен, но сейчас мне не менее любопытно. 1 в надежде, что у кого-нибудь есть ответ.

2. @Endophage: Да, текстовый режим определенно выполняет правильное преобразование n при записи (это хорошо документировано). Обратная операция задается U режимом (универсальный перевод строки).

Ответ №1:

Я думаю, что они означают, что некоторые кодировки используют все 8 бит по крайней мере в нескольких байтах, так что возможны все 256 значений (и, в частности, возможно получить 0x0A или 0x0D, которые не означают CR или LF).

Напротив, в файле UTF-8 символы CR и LF (и все остальные символы ниже 0x80) всегда преобразуются в самих себя. Они не могут отображаться как часть кодировки какого-либо другого символа.

Комментарии:

1. Интересно. Теперь, если я правильно понимаю, вы говорите, что codecs.open() создается файловый объект, который сначала кодирует, а затем выполняет преобразования новой строки, которые могут «повредить» закодированные байты, верно? Я бы ожидал, codecs что мы поступим наоборот: сначала выполним преобразование новой строки, затем закодируем, что позволит codecs.open записывать в текстовом режиме… Это правильно? Если да, то почему они этого не сделали??

2. Хотя эти замечания по поводу UTF-8 интересны, я не понимаю, как они объясняют проблему с «кодировками с использованием 8-битных значений»: ISO-8859-1 (он же Latin 1) также кодирует 8-битные значения, и преобразование новых строк отлично работает с Latin 1, как и с UTF-8. Итак, неясно, в чем проблема с «8-битными кодировками»…

3. … Я бы добавил, что можно представить 7-битные кодировки, которые используют 0x0A и 0x0D как часть кодирования некоторых символов (с которыми, возможно, произошла бы путаница codecs ??). Итак, опять же, я не вижу, что специфично в 8-битных кодировках и их взаимосвязи с codecs.open() принудительным двоичным режимом. Приветствуется любое дополнительное обсуждение!