Why does a R/W transition mid-file in rb+ mode fail, unless I use fseek(fp,0,SEEK_CUR)?Why it works at end of file?

I had never realized this. I could have very well assumed subconsciously as a hard fact that I can transition between reading and writing on an existing file opened it update mode, just like that. But two questions on Stack Overflow (1 and 2) drove me skeptical and I decided to try it out. Here's what I find:

In the first program, prog1, I work on a file source.txt which only has the line Lethal weapon. I read the first world Lethal using fscanf() and intend to write " musket" right after that expecting to get Lethal musket. But it simply fails, and I still get the original content Lethal weapon at the end of the write operation.

But in that first program, if I insert the line fseek(fp, 0, SEEK_CUR), the write operation works fine and I get Lethal musket. I notice that fseek(fp, 0, SEEK_CUR) doesn't serve any purpose, other than call fseek() just for the sake of it, as there isn't any net seeking at all.

But in the second program, prog2, the same scenario doesn't need that fseek(fp, 0, SEEK_CUR) statement. To be exact, in the second program, in contrast to reading to middle of file as in first program, here I read to the end of file, and then start writing there. Here the write is successful even without using fseek(fp, 0, SEEK_CUR) and I get the desired content Lethal weapon sale.

Why can't we transition from read to write mode in the middle of the file and what difference fseek(fp, 0, SEEK_CUR) makes to get it working?

And at the same time, why does the same transition work without any fuss if we read to end of file and write there? Why is fseek(fp, 0, SEEK_CUR) not needed in second case? How advisable is my use of fseek(fp, 0, SEEK_CUR) to make the write successful in the first program? Is there a better alternative?

Two questions on Stack Overflow seem to have addressed the same issue to some extent, but since they were based more on seeking explanation of excerpts from texts/books, the answers oriented towards them doesn't seem to address what I intend to know in precise terms.

// PROG 1

#include <stdio.h>

int main ()
{
    FILE *fp = fopen("D:\\source.txt", "r+");
    char arr[20], brr[50];
    fscanf(fp, "%s", arr);
    printf("String is %s\n", arr);
    //fseek(fp, 0, SEEK_CUR);  // It doesn't work without it
    fprintf(fp, " musket");
    rewind(fp);
    fgets(brr, 50, fp);
    printf("New string is %s", brr);
    fclose(fp);
}

Output:

1) Without fseek() -- Lethal weapon

2) With fseek() -- Lethal musket

// PROG 2

#include <stdio.h>

int main ()
{
    FILE *fp = fopen("D:\\source.txt", "r+");
    char arr[20], brr[50];
    fgets(arr, 20, fp);
    printf("Initial line is %s\n", arr);
    fprintf(fp, " sale"); // writes to end of file
    rewind(fp);
    printf("New string is %s", fgets(brr, 50, fp));
    fclose(fp);
}

Output without fseek():Lethal weapon sale

Upvotes: 3

Views: 553

Answers (1)

Alexander Amelkin
Alexander Amelkin

Reputation: 778

Actually, it looks like a bug in your libc implementation. File I/O streams are usually a libc abstraction over the file descriptor based binary I/O implemented by the OS kernel. So any strange behaviour shall be attributed to your specific libc quirks.

Since you're apparently using Windows, that may be the source of your problems.

There is no such problem with GCC 4.6.1 and glibc-2.13 on Ubuntu 11.10 (Oneiric Ocelot).

Upvotes: 0

Related Questions