views:

71

answers:

4

I am designing an image decoder and as a first step I tried to just copy the using c. i.e open the file, and write its contents to a new file. Below is the code that I used.

while((c=getc(fp))!=EOF)
  fprintf(fp1,"%c",c);

where fp is the source file and fp1 is the destination file. The program executes without any error, but the image file(".bmp") is not properly copied. I have observed that the size of the copied file is less and only 20% of the image is visible, all else is black. When I tried with simple text files, the copy was complete.

Do you know what the problem is?

+3  A: 

Make sure that the type of the variable c is int, not char. In other words, post more code.

This is because the value of the EOF constant is typically -1, and if you read characters as char-sized values, every byte that is 0xff will look as the EOF constant. With the extra bits of an int; there is room to separate the two.

unwind
Yup that was the mistake, first i tried to directly use the getc() without storing it in a variable. then suddenly i declared a char and used it. thanks.
Gan
Awesome catch, unwind.
San Jacinto
+1  A: 

Did you open the files in binary mode? What are you passing to fopen?

eduffy
I used r mode, it worked and I also tried with 'rb' aswell. the mistake was that i declared the variable as char. thanks.
Gan
A: 

It's one of the most "popular" C gotchas.

leonbloy
This explanation is good. Thanks.
Gan
A: 

You should use freadand fwrite using a block at a time

FILE *fd1 = fopen("source.bmp", "r");
FILE *fd2 = fopen("destination.bmp", "w");
if(!fd1 || !fd2)
 // handle open error

size_t l1;
unsigned char buffer[8192]; 

while((l2 = fread(buffer, 1, sizeof buffer, fd1)) > 0) {
  size_t l2 = fwrite(buffer, 1, l1, fd2);
  if(l2 < 0)
   // handle error
 else if(l2 < l1)
  // Handle media full
}
fclose(fd1);
fclose(fd2);

It's substantially faster to read in bigger blocks, and fread/fwrite handle only binary data, so no problem with \n which might get transformed to \r\n in the output (on Windows and DOS) or \r (on (old) MACs)

tristopia
A very good suggestion, I will also use this in my program and see how it works out. Thanks.
Gan