Что такое EOF для двоичных файлов? Состояние? Символ?

Я справился так далеко со знанием того, что EOF является специальным символом, вставляемым автоматически в конец текстового файла для обозначения его конца. Но теперь я чувствую необходимость в дополнительных пояснениях по этому поводу. Я проверил на Google и странице Википедии для EOF но они не могли ответить на следующий вопрос, и для этого также нет точных ссылок переполнения стека. Поэтому, пожалуйста, помогите мне в этом:

  • Моя книга говорит, что файлы в двоичном режиме отслеживают конец файла по количеству символов, присутствующих в записи каталога в файле. (В отличие от текстовых файлов, которые имеют специальный символ EOF для обозначения конца). Так какова история EOF в контексте бинарных файлов? Я запутался, потому что в следующей программе я успешно использую !=EOF Сравнение при чтении из .exe файл в двоичном режиме:

     #include<stdio.h>
     #include<stdlib.h>
    
     int main()
     {
    
      int ch;   
      FILE *fp1,*fp2;
    
      fp1=fopen("source.exe","rb");
      fp2=fopen("dest.exe","wb");
    
      if(fp1==NULL||fp2==NULL)
      {
      printf("Error opening files");
      exit(-1);
      }
    
      while((ch=getc(fp1))!=EOF)
      putc(ch,fp2);
    
      fclose(fp1);
      fclose(fp2);
    
      }
    
  • Является EOF особый "характер" вообще? Или это условие, как говорит Википедия, состояние, при котором компьютер знает, когда возвращать определенное значение, например -1 (EOF на моем компьютере)? Примером такого "условия" является ситуация, когда функция чтения символов заканчивает чтение всех присутствующих символов, или когда функции ввода / вывода символов / строк сталкиваются с ошибкой чтения / записи?

    Интересно, что тег Stack Overflow для EOF смешаны оба эти определения EOF, Тег для EOF сказал: "В области программирования EOF - это последовательность байтов (или символ), который указывает, что после этого больше нет содержимого". в то время как в разделе "о программе" также сказано, что "Конец файла (обычно сокращенно EOF)" - это условие в операционной системе компьютера, при котором данные больше не могут считываться из источника данных. Источник данных обычно называется файлом или поток."

Но у меня сильное чувство EOF не будет символом, так как каждая другая функция, кажется, возвращает его, когда обнаруживает ошибку во время ввода / вывода.

Будет очень мило с вашей стороны, если вы сможете прояснить этот вопрос для меня.

4 ответа

Решение

Различные индикаторы EOF, которые предоставляет вам C, не обязательно имеют какое-либо отношение к тому, как файловая система отмечает конец файла.

Большинство современных файловых систем знают длину файла, потому что они записывают его где-то отдельно от содержимого файла. Процедуры, которые читают файл, отслеживают, где вы читаете, и останавливаются, когда вы достигаете конца. Подпрограммы библиотеки C генерируют значение EOF для возврата к вам; они не возвращают значение, которое на самом деле находится в файле.

Обратите внимание, что EOF, возвращаемый подпрограммами библиотеки C, на самом деле не является символом. Процедуры библиотеки C обычно возвращают intи что int это либо символьное значение, либо EOF. Например, в одной реализации символы могут иметь значения от 0 до 255, а EOF может иметь значение -1. Когда подпрограмма библиотеки встретилась с концом файла, она фактически не увидела символ -1, потому что такого символа нет. Вместо этого основной системной подпрограммой было сказано, что достигнут конец файла, и он ответил, возвращая -1.

Старые и грубые файловые системы могут иметь значение в файле, которое обозначает конец файла. По разным причинам это обычно нежелательно. В простейшей реализации это делает невозможным сохранение произвольных данных в файле, поскольку вы не можете сохранить маркер конца файла как данные. Можно, однако, иметь реализацию, в которой необработанные данные в файле содержат что-то, что указывает на конец файла, но данные преобразуются при чтении или записи, так что произвольные данные могут быть сохранены. (Например, путем "цитирования" маркера конца файла.)

В некоторых случаях такие вещи, как маркеры конца файла, также появляются в потоках. Это обычное явление при считывании с терминала (или псевдотерминала или подобного терминалу устройства). В Windows нажатие клавиши control-Z указывает на то, что пользователь завершил ввод данных, и обрабатывается аналогично для достижения конца файла. Это не означает, что control-Z является EOF. Программное обеспечение, считывающее данные из терминала, видит control-Z, обрабатывает его как конец файла и возвращает указания конца файла, которые, вероятно, отличаются от control-Z. В Unix, control-D - это, как правило, похожий страж, отмечающий конец ввода.

Это должно прояснить это для вас.

По сути, EOF - это просто макрос с предопределенным значением, представляющим код ошибки из функций ввода / вывода, указывающий на то, что больше нет данных для чтения.

Файл на самом деле не содержит EOF. EOF не является своего рода символом - помните, что байт может быть между 0 и 255, поэтому не имеет смысла, если файл может содержать -1. EOF - это сигнал от используемой операционной системы, который указывает, что конец файла достигнут. Обратите внимание, как getc() возвращает int - это значит, что он может возвратить -1, чтобы сообщить, что поток достиг конца файла.

Сигнал EOF обрабатывается одинаково для двоичных и текстовых файлов - фактическое определение двоичного и текстового потока варьируется в зависимости от ОС (например, в двоичном и текстовом режиме * nix это одно и то же). В любом случае, как указано выше, это не является частью самого файла. ОС передает его getc(), чтобы сообщить программе, что конец потока достигнут.

Из библиотеки GNU C:

Этот макрос является целочисленным значением, которое возвращается рядом узкопотоковых функций, чтобы указать состояние конца файла или некоторую другую ситуацию с ошибкой. В библиотеке GNU C EOF равно -1. В других библиотеках его значением может быть другое отрицательное число.

EOF это не персонаж. В этом контексте это -1, что, технически, не является символом (если вы хотите быть предельно точным, можно утверждать, что это может быть символ, но это не имеет значения в этом обсуждении). EOF Просто чтобы быть ясно, это "Конец файла". Когда вы читаете файл, вам нужно знать, когда нужно остановиться, иначе может произойти ряд вещей в зависимости от среды, если вы попытаетесь прочитать файл за концом файла.

Итак, был разработан макрос, чтобы сигнализировать о том, что конец файла был достигнут в ходе чтения файла, что EOF, За getc это работает, потому что возвращает int а не char так что есть дополнительная возможность вернуть что-то кроме char сигнализировать EOF, Другие вызовы ввода / вывода могут сигнализировать EOF по-другому, например, бросая исключение.

Как интересный факт, в DOS (и, возможно, все еще в Windows?) Реальный, физический характер ^Z был помещен в конец файла, чтобы обозначить его конец. Так, на DOS, на самом деле был EOF персонаж. У Unix никогда не было такой вещи.

Что ж, вполне возможно найти EOF двоичного файла, если вы изучите его структуру.

Нет, вам не нужна ОС, чтобы знать EOF исполняемого EOF.

Практически каждый тип исполняемого файла имеет нулевую страницу, которая описывает основную информацию, которая может понадобиться ОС при загрузке кода в память, и хранится как первая страница этого исполняемого файла.

Возьмем пример исполняемого файла MZ. https://wiki.osdev.org/MZ

Здесь, по смещению 2, у нас есть общее количество полных / частичных страниц, а сразу после этого, по смещению 4, у нас есть количество байтов на последней странице. Эта информация обычно используется ОС для безопасной загрузки кода в память, но вы можете использовать ее для вычисления EOF вашего двоичного файла.

Алгоритм:

 1. Start
 2. Parse the parameter and instantiate the file pointer as per your requirement.
 3. Load the first page (zero) in a (char) buffer of default size of page zero and print it. 
 4. Get the value at *((short int*)(&buffer+2)) and store it in a loop variable called (short int) i.
 5. Get the value at *((short int*)(&buffer+4)) and store it in a variable called (short int) l.
 6. i--
 7. Load and print (or do whatever you wanted to do) 'size of page' characters into a buffer until i equals zero.
 8. Once the loop has finished executing just load `l` bytes into that buffer and again perform whatever you wanted to 
 9.  Stop

Если вы разрабатываете свой собственный формат двоичного файла, подумайте о добавлении каких-либо метаданных в начало этого файла или специального символа или слова, обозначающего конец этого файла.

И есть большая вероятность того, что ОС загрузит отсюда размер файла с помощью простых математических вычислений и путем анализа метаданных, даже если может показаться, что ОС хранит его где-то вместе с другой информацией, которую она ожидает store (абстракция для уменьшения избыточности).

Другие вопросы по тегам