简体   繁体   中英

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

This is my program:

#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);
}

At runtime the program crashed with informatoin:

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

But if I uncomment fseek(file1, 0, SEEK_CUR); everything would be fine considering file pointer has not been moved. So why is that? I use Visual Studio 2019


PS Why this works just fine?

#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);
}

Read to write

Pulled from 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 .

Changing between read/write operations require a file-position function, In your code snippet, you have:

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

Since you are changing from read to write, you need to call a file-position function (fsetpos, fseek or rewind).


Write to Read

As for write to read, you will still need to call a file-position function. However to answer why the second code block works, we need to know what fwrite() does on success.

According to the 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.

Consider the code that you have provided:

...
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);
...

Assuming all fwrite()'s succeed, your file pointer would be at the EOF. Since the input operation encounters EOF , the code block would execute just fine.

However, you should follow guidelines and call fsetpos, fseek or rewind should fwrite fail.


Similar Stackoverflow questions

C standard library corner case

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM