To copy files in binary mode,why it doesn't wo

2019-08-30 04:47发布

This question already has an answer here:

The following program is intended to make a copy of one .exe application file.But just one little thing determines whether it indeed gives me a proper copy of the intended file RealPlayer.exe or gives me a corrupted file.

What I do is read from the source file in binary mode and write to the new copy in the same mode.For this I use a variable ch.But if ch is of type char, I get a corrupted file which has a size of few bytes while the original file is 26MB.But if I change the type of ch to int, the program works fine and gives me the exact copy of RealPlayer.exe sized 26MB.So let me ask two questions that arise from this premise.I would appreciate if you can answer both parts:

1) Why does using type char for ch mess things up while int type works?What is wrong with char type?After all, shouldn't it read byte by byte from the original file(as char is one byte itself) and write it byte by byte to the new copy file?After all isn't what the int type does,ie, read 4 bytes from original file and then write that to the copy file?Why the difference between the two?

2) Why is the file so small-sized compared to original file if we use char type for ch?Let's forget for a moment that the copied file is corrupt to begin with and focus on the size.Why is it that the size is so small if we copy character by character (or byte by byte), but is big(original size) when we copy "integer by integer" (or 4-bytes by 4-bytes)?

I was suggested by a friend to simply stop asking questions and use int because it works while char doesn't!!.But I need to understand what's going on here as I see a serious lapse in my understanding in this matter.Your detailed answers are much sought.Thanks.

#include<stdio.h>
#include<stdlib.h>

int main()
{
char ch;   //This is the cause of problem
//int ch;   //This solves the problem
FILE *fp,*tp;

fp=fopen("D:\\RealPlayer.exe","rb");
tp=fopen("D:\\copy.exe","wb");
if(fp==NULL||tp==NULL)
{
    printf("Error opening files");
    exit(-1);
}

while((ch=getc(fp))!=EOF)
putc(ch,tp);

fclose(fp);
fclose(tp);

}

标签: c file-io fopen
2条回答
ら.Afraid
2楼-- · 2019-08-30 05:25

The problem is in the termination condition for the loop. In particular, the type of the variable ch, combined with rules for implicit type conversions.

while((ch=getc(fp))!=EOF)

getc() returns int - either a value from 0-255 (i.e. a char) or -1 (EOF).

You stuff the result into a char, then promote it back to int to do the comparison. Unpleasant things happen, such as sign extension.

Let's assume your compiler treats "char" as "signed char" (the standard gives it a choice).

You read a bit pattern of 0xff (255) from your binary file - that's -1, expressed as a char. That gets promoted to int, giving you 0xffffffff, and compared with EOF (also -1, i.e 0xffffffff). They match, and your program thinks it found the end of file, and obediently stops copying. Oops!

One other note - you wrote:

After all isn't what the int type does,ie, read 4 bytes from original file and then write that to the copy file?

That's incorrect. getc(fp) behaves the same regardless of what you do with the value returned - it reads exactly one byte from the file, if there's one available, and returns that value - as an int.

查看更多
小情绪 Triste *
3楼-- · 2019-08-30 05:31
int getc ( FILE * stream );

Returns the character currently pointed by the internal file position indicator of the specified stream. On success, the character read is returned (promoted to an int value).If you have already defined ch as int all works fine but if ch is defined as char, returned value from getc() is supressed back to char.

above reasons are causing corruption in data and loss in size.

查看更多
登录 后发表回答