The issue is that with fopen/'+'
, switching from reading to writing requires an intermediate call to a file positioning function, e.g. fseek
:
7.21.5.3 The fopen function
(7) 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.
So you probably have to write something like
fseek (fp , -1, SEEK_CUR);
putc(ch,file);
fseek (fp , 0, SEEK_CUR);
Note, however, that replacing characters one by one in a (possibly) large file is rather inefficient. The preferred way would be to read in one file, do the conversions and write to another file, and - in the end - replace the one file with the other one. If that cannot be achieved, try at least to read in / convert / write back larger chunks (not byte by byte).
Just to check whether converting byte by byte is really inefficient, I compared it to a chunk-by-chunk - approach. It turns out - at least at my machine - that chunk-by-chunk in this test is 500 times faster than byte-by-byte. The file size is about 100k:
int main(void) {
FILE *file;
int ch;
file = fopen("/Users/stephanl/Desktop/ImplantmedPic_Storeblok.jpg", "rb+");
if (file == NULL) {
printf("Error: cannot open file.txt\n");
return 1;
} else {
clock_t t1 = clock();
// The following variant takes about 900 ticks:
unsigned char buffer[1000];
unsigned long l;
while (1) {
unsigned long fpi = ftell(file);
l=fread(buffer, 1, 1000, file);
if (l==0)
break;
for (int i=0;i<l;i++) {
buffer[i]=~buffer[i];
}
fseek(file, fpi, SEEK_SET);
fwrite(buffer,1,l, file);
fseek(file, 0L, SEEK_CUR);
}
// this variant takes about 500.000 ticks
while ((ch = fgetc(file)) != EOF) {
fseek(file, -1L, SEEK_CUR);
putc(~ch, file);
fseek(file, 0L, SEEK_CUR);
}
fclose(file);
clock_t t2 = clock();
printf ("difference: %ld \n", t2-t1);
return 0;
}
}