Flush between consecutive read and write ошибка

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?

Это моя программа:

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

1 ответ

Лучший ответ

Прочтите, чтобы написать

Получено из Документация по библиотеке времени выполнения C Microsofts

Когда указан тип доступа «r +», «w +» или «a +», разрешены как чтение, так и запись. (Считается, что файл открыт для «обновления».) Однако при переключении с чтения на запись операция ввода должна встретить маркер EOF . Если EOF отсутствует, вы должны использовать промежуточный вызов функции позиционирования файла. Функции позиционирования файлов — это fsetpos, fseek и rewind. Когда вы переключаетесь с записи на чтение, вы должны использовать промежуточный вызов либо функции fflush, либо функции позиционирования файлов .

Для переключения между операциями чтения / записи требуется функция позиции файла. Во фрагменте кода у вас есть:

...
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 () делает в случае успеха.

Согласно той же документации Microsoft,

… Функция fwrite записывает количество элементов, каждый размером с длину, из буфера в выходной поток. Указатель файла, связанный с потоком (если он есть), увеличивается на количество фактически записанных байтов.

Рассмотрим предоставленный вами код:

...
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. Поскольку операция ввода встречает EOF, блок кода будет выполняться нормально.

Однако вы должны следовать инструкциям и вызывать fsetpos, fseek или rewind, если fwrite не работает.


Похожие вопросы по Stackoverflow

C угловой шкаф для стандартной библиотеки

Почему в режимах обновления между чтением и записью всегда требуется fseek или fflush?


1

Ace Figueroa
10 Май 2020 в 04:23

I am reading and writing a struct to/from a random access file. File pointer is defined in the main function and passed to other functions. I tried to put fflush everywhere that I can yet I still get this error. I don’t know what I am missing.

typedef struct seatdata
{
    int seat_num;
    char name[15];
    char surname[15];
    char gender;
}Seatdata;

void newReservation( FILE* data )
{
    Seatdata buffer;
    int seat_number;

    printf( "Enter seat number to be reserved: " );
    scanf( "%d", &seat_number );

    fseek( data, (seat_number-1)*sizeof(Seatdata), SEEK_SET );

    fread( &buffer, sizeof(Seatdata), 1, data );
    fflush( data );

    if ( buffer.seat_num != 0 )
    {
        printf( "This seat has already been reserved." );
        return;
    }

    printf("Enter name surname and gender: " );

    scanf("%s %s %c", buffer.name, buffer.surname, &buffer.gender );


    fwrite( &buffer, sizeof(Seatdata), 1, data );
    fflush( data );
} 

int main ( void )
{
    FILE* data = NULL;
    data = fopen( "bus.dat", "rb+" );
    if ( data == NULL ) { return -1; }

    newReservation( data );

    return 0;
}

Error comes at the fwrite part. And apparently I am required to pass the FILE* to functions. ( This is an assignment )

  • Related Question
  • Related Blog
  • Related Tutorials

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.

I am reading and writing a struct to/from a random access file. File pointer is defined in the main function and passed to other functions. I tried to put fflush everywhere that I can yet I still get this error. I don’t know what I am missing.

typedef struct seatdata
{
    int seat_num;
    char name[15];
    char surname[15];
    char gender;
}Seatdata;

void newReservation( FILE* data )
{
    Seatdata buffer;
    int seat_number;

    printf( "Enter seat number to be reserved: " );
    scanf( "%d", &seat_number );

    fseek( data, (seat_number-1)*sizeof(Seatdata), SEEK_SET );

    fread( &buffer, sizeof(Seatdata), 1, data );
    fflush( data );

    if ( buffer.seat_num != 0 )
    {
        printf( "This seat has already been reserved." );
        return;
    }

    printf("Enter name surname and gender: " );

    scanf("%s %s %c", buffer.name, buffer.surname, &buffer.gender );


    fwrite( &buffer, sizeof(Seatdata), 1, data );
    fflush( data );
} 

int main ( void )
{
    FILE* data = NULL;
    data = fopen( "bus.dat", "rb+" );
    if ( data == NULL ) { return -1; }

    newReservation( data );

    return 0;
}

Error comes at the fwrite part.
And apparently I am required to pass the FILE* to functions. ( This is an assignment )

  •  
  • c

  • visual-c++

  • stdio

  •  13-09-2020
  •  | 

  •  

Question

Is the following program a valid C program?

#include <stdio.h>

int main()
{
    fwrite("x", 1, 1, stderr);
    fflush(stderr);
    fgetc(stderr);
    fwrite("y", 1, 1, stderr);
    return 0;
}

Notice that I try to read from stderr.

When I compile it in Visual C++ 2008, and run it, I get the following output:

xy

which makes sense. However, when I redirect stderr to a file (test.exe 2> foo.txt), I get a
«Debug Assertion Failed» window with the message: «Inconsistent Stream Count. Flush between consecutive read and write». Adding a fflush between the read and write does fix the problem.
(This happens in debug build. In release builds, the second write silently fails).

Is this behavior correct, or is this a compiler library bug? I couldn’t find anywhere any rules describing when reads or writes are illegal in C.

Solution

C99 says in 7.19.5.3 (fopen), paragraph 6:

When a file is opened with update mode ('+' as the second or third character in the above list of mode argument values), both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the fflush function […], and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.

Congratulations for discovering this corner case in practice. The library implementation is completely correct, since you violate the shall quoted above.

And by the way, it is not uncommon to read from stderr. This is useful when stdin and stdout are redirected and no terminal is available. Although C99 doesn’t guarantee it to be readable, I remember some cases on POSIX-like systems where this had actually been done.

  • Fltmgr file system windows 10 ошибка
  • Fls fuel level ошибка
  • Flowsic 600 ошибка 3003
  • Floppy drive cntrlr error or no cntrlr present описание ошибки
  • Floor generator ошибка invalid input mesh detected