Почему досрочное продвижение в EOF?
Я пишу библиотеку C, которая читает файл в памяти. Он пропускает первые 54 байта файла (заголовок), а затем считывает остаток в виде данных. Я использую fseek, чтобы определить длину файла, а затем использовать fread для чтения в файле.
Цикл запускается один раз, а затем заканчивается, потому что достигается EOF (без ошибок). В конце, bytesRead = 10624, ftell (stream) = 28726, а буфер содержит 28726 значений. Я ожидаю, что fread будет читать 30 000 байт, а позиция файла будет равна 30054 при достижении EOF.
C не является моим родным языком, поэтому я подозреваю, что у меня есть туманная ошибка начинающего.
Код выглядит следующим образом:
const size_t headerLen = 54;
FILE * stream;
errno_t ferrno = fopen_s( &stream, filename.c_str(), "r" );
if(ferrno!=0) {
return -1;
}
fseek( stream, 0L, SEEK_END );
size_t bytesTotal = (size_t)(ftell( stream )) - headerLen; //number of data bytes to read
size_t bytesRead = 0;
BYTE* localBuffer = new BYTE[bytesTotal];
fseek(stream,headerLen,SEEK_SET);
while(!feof(stream) && !ferror(stream)) {
size_t result = fread(localBuffer+bytesRead,sizeof(BYTE),bytesTotal-bytesRead,stream);
bytesRead+=result;
}
В зависимости от используемой ссылки, совершенно очевидно, что добавление "b" к флагу режима является ответом. Ищите кандидатуры на значок кости.: -)
Эта ссылка говорит об этом во втором абзаце второго предложения (хотя и не в их таблице).
MSDN не обсуждает двоичный флаг до половины страницы.
OpenGroup упоминает существование тега "b", но заявляет, что он "не будет иметь никакого эффекта".
Ответы
Ответ 1
возможно, это проблема двоичного режима. Попробуйте открыть файл с помощью "r+b"
в качестве режима.
EDIT: как отмечено в комментарии "rb"
, скорее всего, будет лучше соответствовать вашему первоначальному намерению, так как "r+b"
откроет его для чтения/записи и "rb"
доступен только для чтения.
Ответ 2
Также стоит отметить, что просто включение binmode.obj в вашу ссылку будет делать это для вас для открытия всех файлов.
Ответ 3
Решение, основанное на предыдущих ответах:
size_t bytesRead = 0;
BYTE* localBuffer = new BYTE[bytesTotal];
fseek(stream,headerLen,SEEK_SET);
while(!feof(stream) && !ferror(stream)) {
size_t result = fread(localBuffer+bytesRead,sizeof(BYTE),bytesTotal-
bytesRead,stream);
bytesRead+=result;
}