为什么我在使用 fwrite() 和 fread() 时遇到一些问题?

Why do I have some trouble with fwrite() and fread()?

这是我的程序:

#include <iostream>

int main()
{
    // open file1.txt
    FILE* file1;
    fopen_s(&file1, "file1.txt", "wb+");

    // write array of 5 integers to file.txt
    int array1[5] { 1, 2, 3, 4, 5 };
    for (int i = 0; i < 5; i++)
    {
        fwrite(array1, sizeof(array1[0]), 5, file1);
    }

    fseek(file1, 0, SEEK_SET);
    int tempValue;
    fread(&tempValue, sizeof(tempValue), 1, file1);
    // fseek(file1, 0, SEEK_CUR);
    fwrite(&tempValue, sizeof(tempValue), 1, file1);
}

在运行时程序崩溃并显示以下信息:

>     Expression ("Flush between consecutive read and write.",                 
>     !stream.has_any_of(_IOREAD))

但是如果我取消注释 fseek(file1, 0, SEEK_CUR); 考虑到文件指针尚未移动,一切都会好起来的。那是为什么呢? 我用 Visual Studio 2019


P.S。 为什么这很好用?

#include <iostream>

int main()
{
    FILE* file1;
    fopen_s(&file1, "data.txt", "wb+");
    int value = 7;
    fwrite(&value, sizeof(value), 1, file1);
    fwrite(&value, sizeof(value), 1, file1);

    fseek(file1, 0, SEEK_CUR);
    fwrite(&value, sizeof(value), 1, file1);
    fread(&value, sizeof(value), 1, file1);
}

读写

来自 Microsofts C Runtime Library documentation

When the "r+", "w+", or "a+" access type is specified, both reading and writing are allowed. (The file is said to be open for "update".) However, when you switch from reading to writing, the input operation must encounter an EOF marker. If there is no EOF, you must use an intervening call to a file-positioning function. The file-positioning functions are fsetpos, fseek, and rewind. When you switch from writing to reading, you must use an intervening call to either fflush or to a file-positioning function.

在 read/write 操作之间切换需要文件位置函数, 在您的代码片段中,您有:

...
fseek(file1, 0, SEEK_SET);
int tempValue;
fread(&tempValue, sizeof(tempValue), 1, file1);
// fseek(file1, 0, SEEK_CUR);
fwrite(&tempValue, sizeof(tempValue), 1, file1);
...

由于要从读取更改为写入,因此需要调用文件位置函数(fsetpos、fseek 或 rewind)。


写入读取

至于写读,还是需要调用文件定位函数。然而,要回答为什么第二个代码块有效,我们需要知道 fwrite() 在成功时做了什么。

根据same Microsoft documentation

... The fwrite function writes up to count items, of size length each, from buffer to the output stream. The file pointer associated with stream (if there is one) is incremented by the number of bytes actually written.

考虑您提供的代码:

...
FILE* file1;
fopen_s(&file1, "data.txt", "wb+");
int value = 7;
fwrite(&value, sizeof(value), 1, file1);
fwrite(&value, sizeof(value), 1, file1);

fseek(file1, 0, SEEK_CUR);
fwrite(&value, sizeof(value), 1, file1);
fread(&value, sizeof(value), 1, file1);
...

假设所有 fwrite() 都成功,您的文件指针将位于 EOF。 Since the input operation encounters EOF,代码块会执行得很好。

但是,您应该遵循指南并在 fwrite 失败时调用 fsetpos、fseek 或 rewind。


类似的 Whosebug 问题

C standard library corner case

Why is fseek or fflush always required between reading and writing in the update modes?