2008-09-28 6 views
8

Очень просто говоря, у меня есть следующий фрагмент кода:Конец FILE * указатель не равен размеру записанных данных

FILE* test = fopen("C:\\core.u", "w"); 
printf("Filepointer at: %d\n", ftell(test)); 
fwrite(data, size, 1, test); 
printf("Written: %d bytes.\n", size); 
fseek(test, 0, SEEK_END); 
printf("Filepointer is now at %d.\n", ftell(test)); 
fclose(test); 

и выводит:

Filepointer at: 0 
Written: 73105 bytes. 
Filepointer is now at 74160. 

Почему? Почему количество написанных байтов не соответствует указателю на файл?

+2

Я рекомендую не использовать пути стиля NT в аргументах fopen(). Windows также поддерживает POSIX-пути, которые переносимы и не требуют экранирования '\'. – Terminus 2008-10-01 09:14:29

ответ

19

Поскольку вы открываете файл в текстовом режиме, он преобразует маркеры конца строки, такие как LF, в CR/LF.

Это, скорее всего, если вы работаете в Windows (и вы, вероятно, знаете, что ваше имя файла начинается с "c:\").

Если открыть файл в режиме "wb", я подозреваю, что вы найдете номера идентичны:

FILE* test = fopen("C:\\core.u", "wb"); 

Стандарт C99 это сказать в 7.19.5.3 The fopen function:

Режим аргумент указывает на строку. Если строка является одной из следующих, файл открыт в указанном режиме. В противном случае поведение не определено.

r открыт текстовый файл для чтения
w усечение до нулевой длины или создать текстовый файл для записи
a Append; открыть или создать текстовый файл для записи в конец файла из-
rb открытый двоичный файл для чтения
wb усечение до нулевой длины или создать двоичный файл для записи
ab Append; открыть или создать двоичный файл для записи в конец файла из-
r+ открыт текстовый файл для обновления (чтение и запись)
w+ усечение до нулевой длины или создать текстовый файл для обновления
a+ дописывания; открыть или создать текстовый файл для обновления, написание на конец из файла
r+b или rb+ открытый двоичный файл для обновления (чтение и запись)
w+b или wb+ укоротить до нулевой длины или создать двоичный файл для обновления
a+b или ab+ присоединять; открыть или создать двоичный файл для обновления, написание на конец из файла

Вы можете видеть, что они различают w и wb. Я не верю, что реализация требуется, чтобы обрабатывать два по-разному, но обычно безопаснее использовать двоичный режим для двоичных данных.

+1

Это, пожалуй, довольно темный угол языка. Один стремится не знать, что он есть, пока их не укусили. Хорошо поймал! – fbrereto 2010-02-13 00:07:18

+0

Стоит отметить, что POSIX требует реализации **, чтобы не относиться к ним иначе. – 2011-03-25 14:03:50

0

Что произойдет с возвратом fwrite? обычно возвращаемое значение должно быть числом записанных байтов. Кроме того, что ответ fttel() отвечает прямо перед fseek?

Это может помочь узнать, какая операционная система, версия компилятора C и библиотека C.

0

Файл-указатель - это файл cookie. Это не имеет значения. Единственное, что вы можете использовать, это искать одно и то же место в файле. Я даже не уверен, что ISO C гарантирует, что ftell вернет значения. Если вы не верите этому, просмотрите различные режимы seek(). Они существуют именно потому, что позиция не является простым смещением байта.

0

окна фактически не записывают все данные в файл без флеша и, возможно, fsync. Возможно, поэтому