Я знаю, что должен открыть использование двоичного файла "rb"
вместо "r"
потому что Windows ведет себя по-другому для двоичных и недвоичных файлов.
Но я не понимаю то, что точно происходит, если я открываю файл неправильный путь и почему это различие даже необходимо. Другие операционные системы, кажется, делают прекрасный путем обработки обоих видов файлов то же.
Этот режим предназначен для преобразования окончаний строк.
При чтении в текстовом режиме собственные окончания строк платформы ( \ r \ n
в Windows) преобразуются в окончания строк в стиле Python \ n
. При записи в текстовом режиме происходит обратное.
В двоичном режиме такое преобразование не выполняется.
Другие платформы обычно прекрасно обходятся без преобразования, потому что они изначально хранят окончания строк как \ n
. (Исключением является Mac OS, которая раньше использовала \ r
.) Код, основанный на этом, однако, не переносим.
В Windows текстовый режим преобразует новую строку \n
в возврат каретки, за которым следует новая строка \r\n
.
Если вы читаете текст в двоичном режиме, то проблем не возникает. Если вы читаете двоичные данные в текстовом режиме, они, скорее всего, будут повреждены.
Для чтения файлов разницы быть не должно. При записи в текстовые файлы Windows автоматически испортит ваши переносы строк (добавит \r
перед \n
). Вот почему вы должны использовать "wb"
.
Ну это по историческим (или, как я люблю говорить, истерическим) причинам. Режимы открытия файлов унаследованы от библиотеки C stdio, и поэтому мы следуем им.
Для Windows нет разницы между текстовыми и двоичными файлами, как и в любом из клонов Unix. Нет, я серьезно! - Есть (были) файловые системы/ОС, в которых текстовый файл - это совершенно другой зверь, чем объектный файл и так далее. В некоторых нужно было заранее указывать максимальную длину строк, использовались записи фиксированного размера... ископаемые со времен 80-колоночных бумажных перфокарт и тому подобного. К счастью, в Unices, Windows и Mac такого нет.
Однако - при прочих равных условиях - Unix, Windows и Mac истерически отличаются тем, какие символы они используют в выходном потоке для обозначения конца строки (или, что то же самое, в качестве разделителя между строками). В Unix используется \x0A (\n). В Windows используется последовательность из двух символов \x0D\x0A (\r\n); в Mac - просто \xOD (\r). Вот несколько подсказок о происхождении использования этих двух символов - ASCII код 10 называется Line Feed (LF) и при передаче на телетайп заставляет его двигаться вниз на одну строку (Y++), не меняя своего горизонтального положения (X). Возврат каретки (CR) - ASCII 13 - с другой стороны, заставит печатающую каретку вернуться в начало строки (X=0) без прокрутки на одну строку вниз. Поэтому при отправке вывода на принтер необходимо было отправить и \r, и \n, чтобы каретка переместилась в начало новой строки. Теперь при наборе текста на клавиатуре терминала операторы, естественно, должны нажимать одну клавишу, а не две для конца строки. На Apple][ такой клавишей была клавиша "Return" (\r).
Во всяком случае, так обстояли дела. Создатели Си были озабочены переносимостью - большая часть Unix была написана на Си, в отличие от прежних времен, когда ОС писались на ассемблере. Поэтому они не хотели иметь дело с причудами каждой платформы в отношении представления текста, поэтому они добавили этот злой хак в свою библиотеку ввода-вывода, в зависимости от платформы, ввод и вывод в файл будет "исправлен" на лету так, что программа будет видеть новые строки праведным, Unix-way - как '\n' - независимо от того, было ли это '\r\n' из Windows или '\r' из Mac. Таким образом, разработчику не нужно было беспокоиться о том, на какой ОС работает программа, она все равно могла читать и записывать текстовые файлы в родном формате.
Однако была проблема - не все файлы являются текстовыми, есть и другие форматы, и в них очень чувствительны к замене одного символа на другой. Поэтому они решили, что мы будем называть такие файлы "бинарными" и указывать это fopen()
, включая 'b' в режим - и это будет флажком для библиотеки, чтобы она не делала никакого скрытого преобразования. Вот так все и получилось :)
Итак, если файл открыт с 'b' в двоичном режиме, то никаких преобразований не будет. Если же он был открыт в текстовом режиме, то в зависимости от платформы могут произойти некоторые преобразования символов новой строки (символов) - с точки зрения Unix. Естественно, на платформе Unix нет никакой разницы между чтением/записью в "текстовый" или "бинарный" файл.