12

Why the code below does not work? I mean, it shows all kinds of weird characters on console output.

#include <stdio.h>
char mybuffer[80];
int main()
{
    FILE * pFile;
    pFile = fopen ("example.txt","r+");
    if (pFile == NULL) perror ("Error opening file");

    else {
        fputs ("test",pFile);

        fgets (mybuffer,80,pFile);
        puts (mybuffer);
        fclose (pFile);
        return 0;
    }
}

However, the code below works well.

#include <stdio.h>
char mybuffer[80];
int main()
{
    FILE * pFile;
    pFile = fopen ("example.txt","r+");
    if (pFile == NULL) perror ("Error opening file");

    else {
        fputs ("test",pFile);
        fflush (pFile);    
        fgets (mybuffer,80,pFile);
        puts (mybuffer);
        fclose (pFile);
        return 0;
    }
}

Why I need to flush the stream in order to get the correct result?

Stephen
  • 1,607
  • 2
  • 18
  • 40
Jaebum
  • 1,397
  • 1
  • 13
  • 33

3 Answers3

13

Because the standard says so (§7.19.5.3/5):

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 or to a file positioning function (fseek, fsetpos, or rewind), 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.

There is a reason for this: output and input are normally buffered separately. When there's a flush or seek, it synchronizes the buffers with the file, but otherwise it can let them get out of synch. This genarally improves performance (e.g. when you do a read, it doesn't have to check whether the position you're reading from has been written since the data was read into the buffer).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • 1
    @Lee: Simple, you read it from the point where you left off writing, you need to seek back to the beginning for that to work. – falstro Feb 09 '10 at 17:22
  • @Lee:because the "Test" that you wrote hasn't been read into the read buffer. A probable scenario is that when you open the file, it attempts to fill the read buffer. Since the file is empty, it sets a flag to say no input is available. Until you do a flush or seek, it's going to remain marked that way, so all attempts at reading will fail. – Jerry Coffin Feb 09 '10 at 17:33
7

When using a file with a read/write mode you must call fseek/fflush before different i/o operations.

See this answer on why fseek or fflush is always required...

Community
  • 1
  • 1
Robert Groves
  • 7,574
  • 6
  • 38
  • 50
2

its because C file io works using a buffer. This is only written to disk when you flush it, you write a /n character or you fill the buffer up.

So in the first case, your file contains nothing when you come to read from it.

gbjbaanb
  • 51,617
  • 12
  • 104
  • 148
  • But it still does not work even if I use "test\n" instead of "test". – Jaebum Feb 09 '10 at 16:32
  • The answer is wrong in this regard: Writing `\n` to the file has no effect at all; you must flush the file or write so much data that the C library will flush by itself (usually 4KiB). – Aaron Digulla Feb 09 '10 at 16:38
  • I think the \n bit depends on the implementation - MS does, at least for C++ code. – gbjbaanb Feb 09 '10 at 18:51