Когда вы открываете файл в Python, по умолчанию вы открываете его в Text-mode .Это означает, что двоичные данные декодируются на основе значений по умолчанию операционной системы или явно заданных кодеков.
Как и все данные, текстовые данные на вашем компьютере представлены байтами.Большая часть английского алфавита представлена в виде одного байта, например буква «А» обычно переводится на число 65 или в двоичном виде: 01000001
.Эта кодировка (ASCII) подходит для многих случаев, но когда вы хотите написать текст на таких языках, как румынский, этого уже недостаточно, поскольку символы ă
, ţ
и т. Д. Не являются частью ASCII.
Некоторое время люди использовали разные кодировки для каждого языка (группы), например, группу кодировок Latin-x (ISO-8859-x) для языков, основанных на латинском алфавите, и другие кодировки для других (особенно *).1010 * CJK ) языков.
Если вы хотите представить некоторые азиатские языки или несколько разных языков, вам потребуются кодировки, которые кодируют один символ в несколько байтов.Это может быть либо фиксированное число (например, в UTF-32 и UTF-16), либо переменное число, как в самой распространенной на сегодняшний день кодировке UTF-8.
Назад к Python: Строковый интерфейс Python обещает множество свойств, в том числе произвольный доступ в сложности O (1), что означает, что вы можете получить 1245-й символ даже из очень длинной строки очень быстро.Это противоречит компактной кодировке UTF-8: поскольку один «символ» (на самом деле: одна кодовая точка Unicode) иногда составляет один, а иногда и несколько байтов, Python не может просто перейти к адресу памяти start_of_string + length_of_one_character * offset
, так как length_of_one_character
варьируется в UTF-8.Поэтому Python должен использовать кодирование с фиксированной байтовой длиной.
По причинам оптимизации он не всегда использует UCS-4 (~ UTF-32), потому что это будет тратить много места при текст только для ASCII.Вместо этого Python динамически выбирает Latin-1, UCS-2 или UCS-4 для внутреннего хранения строк.
Чтобы свести все воедино с примером:
Скажите, что вы хотитесохранить строку «soluţie» в памяти из файла, закодированного как UTF-8.Поскольку для представления буквы ţ
требуется два байта, Python выбирает UCS-2:
characters | s | o | l | u | ţ | i | e
utf-8 |0x73 |0x6f |0x6c |0x75 |0xc5 0xa3|0x69 |0x65
ucs-2 |0x00 0x73|0x00 0x6f|0x00 0x6c|0x00 0x75|0x01 0x63|0x00 0x69|0x00 0x65
Как видите, UTF-8 (файл на диске) требуется 8 байтов, тогда как UCS-2 -14.
Добавьте к этому накладные расходы на строку Python и сам интерпретатор Python, и ваши вычисления снова обретут смысл.
Когда вы открываете файл в двоичном режиме (* 1039)*), вы не декодируете байты, а принимаете их как есть.Это проблематично, если в файле есть текст (потому что для обработки данных вы рано или поздно захотите преобразовать его в строку, где вам придется выполнять декодирование), но если это действительно двоичные данные, такиекак изображение, это хорошо (и лучше).
Этот ответ содержит упрощения.Используйте с осторожностью.