Перемещает ли fseek() указатель файла в начало файла, если он был открыт в режиме "a + b"?
Я хочу открыть файл, используя режим "a + b", т.е. если он не существует, он создается автоматически, но если это не так, я не хочу его перезаписывать. Я хочу иметь возможность читать и писать в файл.
Файл двоичный, и я хочу сохранить записи определенного struct
в нем. Поэтому я хочу сделать fseek()
в записи, которую хочу, а затем сохранить запись, используя fwrite()
.
Код выглядит следующим образом (MyRecord
- это typedef
до struct
, а FILENAME
- #define
для имени файла):
int saveRecord(MyRecord *pRecord, int pos)
{
FILE* file = fopen(FILENAME, "a+b");
if (file == NULL)
{
printf("Unable to open file %s\n", FILENAME);
return 0;
}
fseek(file, pos * sizeof(MyRecord), SEEK_SET);
fwrite(pRecord, sizeof(MyRecord), 1, file);
fclose(file);
return 1;
}
Однако этот код просто добавляет запись в конец файла, даже если я установил pos
в 0. Почему не работает fseek()
с SEEK_SET
в режиме добавления?
Я знаю, что могу просто открыть его с помощью "r + b", и если он не сможет открыть его с помощью "wb", но я хочу знать, почему это не работает и почему fseek()
с SEEK_SET
покидает указатель файла в конце. Любые ссылки на места, где это поведение документировано, оценены (потому что я не смог найти никого, или я использую неправильные ключевые слова).
Ответы
Ответ 1
Это потому, что в режиме a
запись в FILE*
всегда добавляется к концу. fseek
только устанавливает указатель чтения в этом режиме. Это описано в стандарте C, 7.19.5.3 fopen:
Открытие файла с добавлением режима ('a'
в качестве первого символа в аргументе режима) приводит к тому, что все последующие записи в файл будут принудительно перенесены в текущий текущий конец файла, независимо от входящих вызовов функции fseek
.
Ответ 2
Используйте режим "r + b" и отключайтесь до "w + b", если он не работает.
Режим "a + b" позволяет читать и добавлять; "r + b" позволяет случайное чтение и запись.
Документация для fopen
описывает, как файл ведет себя с разными режимами.
Ответ 3
Plain C не имеет разумного способа достижения желаемого. Если вы находитесь в системе POSIX или удаленно закрыты, вы можете использовать fd=open(FILENAME, O_CREAT|O_RDRW, 0666)
, а затем fdopen(fd, "rb+")
.
Изменить: Еще одна вещь, которую вы могли бы попробовать, с простым C:
f = fopen(FILENAME, "a+b");
if (!f) /* ... */
tmp = freopen(0, "r+b", f);
if (tmp) f = tmp;
else /* ... */