Different fwrite behavior between Linux and Windows

I have a small sample program written in C. I have a main function that calls the writeFile function, which writes some numbers in a binary file. Then I call overwrite to replace 0 with 1, and finally 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 as follows:

  ---------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 the last number has changed. Can someone help me understand why this is happening?

Another problem is that in overwrite I have to use i to stop this time, because without 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 using gcc 5.1.1.

Thanks everyone

+6
source share
2 answers

This is because you need fflush() after fwrite() , since you should not call fread() after calling fwrite() without an intermediate call to fflush() ,

This is a section of the standard that matters in this case.

7.21.5.3 fopen function

  1. When a file is opened in update mode ( '+' as the second or third character in the above list of values โ€‹โ€‹of the mode argument), both input and output can be performed in a linked thread. However, the output should not be accompanied by an input without an intermediate call to the fflush function or the file positioning function ( fseek , fsetpos or rewind ), and the input should not be accompanied by a direct exit without an intermediate call to the file positioning function, unless the input operation encounters the end of the file. Opening (or creating) a text file with update mode may instead open (or create) a binary stream in some implementations.

It is strange that this section is inside the fopen() function, since it includes fread() and fwrite() , where I searched for the answer.

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

+6
source

MSDN Status for Stream I / O :

Input can be output directly only with an intermediate call to fflush or to the file positioning function ( fseek , fsetpos or rewind ). An output can follow an input without an intermediate call to the file positioning function if the input operation meets the end of the file.

So you need to call fflush() after calling fwrite:

 void overwrite() { FILE *fp = fopen("test.dat", "rb+"); if (fp) { int r; while (fread(&r, sizeof(int), 1, fp) == 1) { if (r == 0) { r = 1; fseek(fp,-sizeof(int),SEEK_CUR); fwrite(&r,sizeof(int),1,fp); fflush(fp); /* Flush here */ } } fclose(fp); /* Also: call fclose() only when fopen() succeeded */ } } 
+2
source

Source: https://habr.com/ru/post/989947/


All Articles