Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different behaviour of fwrite between Linux and Windows

I have a small example program written in C. I have a main that call a function writeFile that writes some numbers in a binary file. Then I call overwrite to replace 0 with 1 and finally I print the result.

This is the code:

#include <stdio.h>

/* Print the content of the file */
void printFile(){
    printf("Read test.dat:\n");
    int r;
    FILE* fp = fopen("test.dat", "rb+");
    if(fp) {
    while(fread(&r,sizeof(int),1,fp)){
            printf("%d\n", r);
        }
    }
    fclose(fp);
}

/* Replace 0 with 1 */
void overwrite(){
    int   r;
    FILE *fp = fopen("test.dat", "rb+");
    if (fp) {
        int i=0;
        while (i < 4 && fread(&r, sizeof(int), 1, fp)) {
            i++;
            if (r == 0) {
                r = 1;
                fseek(fp,-sizeof(int),SEEK_CUR);
                fwrite(&r,sizeof(int),1,fp);
            }
        }
    }
    fclose(fp);    
}

/* Create original file */
void writeFile() {
    int b, b1, b2, b3, b4;

    b  = 3;
    b1 = 2;
    b2 = 0;
    b3 = 4;

    FILE *fp = fopen("test.dat", "wb");
    if (fp) {
        fwrite(&b, sizeof(int), 1, fp);
        fwrite(&b1, sizeof(int), 1, fp);
        fwrite(&b2, sizeof(int), 1, fp);
        fwrite(&b3, sizeof(int), 1, fp);
    }
    fclose(fp);    
}

int main() {
    writeFile();
    printf("---------BEFORE--------\n");
    printFile();
    printf("-----------------------\n");
    printf("Overwriting...\n");
    overwrite();
    printf("---------AFTER---------\n");
    printFile();
    return 0;
}

This code works with Linux, but when I run the same code on Windows the output is this:

 ---------BEFORE--------
Read test.dat:
3
2
0
4
-----------------------
Overwriting...
---------AFTER---------
Read test.dat:
3
2
1
2

Not only 0 was replaced by 1 but also the last number changed. Someone can help me to understand why this happens?

Another problem is that in the overwrite I must use i to stop the while because without the i<4 I get an infinite loop (only with Windows).

I tested this code on Windows 8.1 compiled with gcc 4.8.1 (from MinGW). On my Linux machine I tested the code with gcc 5.1.1.

Thank you all,

like image 646
RobotMan Avatar asked Jun 29 '15 12:06

RobotMan


1 Answers

It's because you need to fflush() after the fwrite(), since you should not call fread() after calling fwrite() without an intervening call to fflush(),

This is the section of the standard that is relevant in this case

7.21.5.3 The fopen function

  1. 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. Opening (or creating) a text file with update mode may instead open (or create) a binary stream in some implementations.

It's weird that this section is within fopen() function since it involves fread() and fwrite(), which is where I was looking for an answer.

You can also see that my previous answer worked but not for the reason I stated in it, instead the explanation is found in the paragraph above.

like image 50
Iharob Al Asimi Avatar answered Sep 19 '22 02:09

Iharob Al Asimi