Перемещает ли fseek () указатель на начало файла, если он был открыт в режиме «a + b»? - PullRequest
12 голосов
/ 04 апреля 2011

Я хочу открыть файл в режиме «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 оставляет указатель файла в конце. Любые ссылки на места, где это поведение задокументировано, приветствуются (потому что я не смог их найти, или я использую неправильные ключевые слова).

Ответы [ 3 ]

18 голосов
/ 04 апреля 2011

Это потому, что в режиме a запись в FILE* всегда заканчивается до конца.fseek только устанавливает указатель чтения в этом режиме.Это задокументировано в стандарте C: 7.19.5.3 fopen :

Открытие файла с режимом добавления ('a' в качестве первого символа в аргументе mode) вызывает все последующиевыполняет запись в файл, который будет принудительно перенесен в текущий текущий конец файла, независимо от промежуточных вызовов функции fseek.

4 голосов
/ 04 апреля 2011

Обычный С не имеет вменяемого способа достичь того, чего вы хотите.Если вы используете систему POSIX или что-то удаленно близкое, вы можете использовать fd=open(FILENAME, O_CREAT|O_RDRW, 0666), а затем fdopen(fd, "rb+").

Edit: Еще одну вещь, которую вы можете попробовать, с простым C:

f = fopen(FILENAME, "a+b");
if (!f) /* ... */
tmp = freopen(0, "r+b", f);
if (tmp) f = tmp;
else /* ... */
4 голосов
/ 04 апреля 2011

Используйте режим «r + b» и переходите к «w + b», если он не работает.

Режим «a + b» позволяет читать и добавлять;«r + b» позволяет произвольное чтение и запись.

В документации для fopen описывается, как файл ведет себя в различных режимах.

...