To copy files in binary mode,why it doesn't work when we read to and write from a character variable? [duplicate]

前提是你 提交于 2019-12-13 04:58:37

问题


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);

}

回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/16475918/to-copy-files-in-binary-mode-why-it-doesnt-work-when-we-read-to-and-write-from

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!