2 #include <stdlib.h>
3
4 int main(int argc,char *argv[])
5 {
6 int ch;
7 FILE *fpinPtr,*fpoutPtr;
8
9 if (argc!=3)
10 {
11 printf("File copy program.\n\n");
12 printf("Usage: command source_file target_file\n");
13 printf("Usage example: \"copy src.txt obj.txt\"\n");
14 exit(EXIT_FAILURE);
15 }
16
17 if ((fpinPtr=fopen(argv[1],"rb"))==NULL)
18 {
19 printf("Input file \"%s\" could not be opened\n",argv[1]);
20 exit(EXIT_FAILURE);
21 }
22
23 if ((fpoutPtr=fopen(argv[2],"wb"))==NULL)
24 {
25 printf("Outout file \"%s\" could not be opened\n",argv[2]);
26 exit(EXIT_FAILURE);
27 }
28
29 while(!feof(fpinPtr))
30 {
31 ch=fgetc(fpinPtr);
32 if(ch>-1)
33 fputc(ch,fpoutPtr);
34 }
35
36 fclose(fpinPtr);
37 fclose(fpoutPtr);
38
39 return 0;
40 }
41
结果这次仔细看了一下,发现了一些小问题.
这条CP命令是读取源文件单个字符然后写入目标文件的方法实现的.但是代码的第6行的变量类型是int,我想这不是浪费内存空间么,而且第32行有一句if(ch>-1) ,半天没搞懂当时写这段代码的程序员是怎么想的.于是,我把第6行改成 char ch; ,删除了第32行的代码.
编译链接一切正常,运行,校验源文件和目标文件的MD5值,不一样.晕了.
仔细对比源文件和目标文件,发现目标文件尾多了一个EOF字符,原来是这个道理.于是把原32行的代码改成if(ch > EOF),复制了一个文本文件,一切正常.然后又试着复制一个BMP文件,问题又来了.
复制位图文件后发现,目标文件比源文件要小很多,用记事本打开源文件,发现源文件里面就有许多EOF字符,这些字符都复制丢了.
而不加原始代码里32行的那句约束语句,则程序会多读取一个字符,如果是读取一个文件段,则会造成读取垃圾数据.
而原始代码正是解决了判断文件尾的问题.
网上有的帖子也说:
可以用feof()函数判断文件尾
也可以用fgetc读取内容
ch=fgetc(fp);
ch==EOF也是文件结尾
看来也不完全对,如果用fgetc来判断,则有可能在读取位图这类二进制文件时会造成错误的文件尾提示,用feof则会多读取一次.
在此之前,我的师兄王晔用判断文件大小的方法复制文件,对小文件的操作或许可以采用.
附师兄的源码:
2 #include <stdlib.h>
3 #define FILE_NAME "a.jpg"
4 int main(void)
5 {
6 char tmp;
7 long len;
8 unsigned char *read_ptr;
9 FILE *p = fopen(FILE_NAME, "rb");
10 FILE *f = fopen("a1.jpg", "wb");
11
12 if(NULL == p)
13 return 1;
14
15 fseek(p, 0L, SEEK_END);
16 len = ftell(p); /*求文件长度*/
17 fseek(p, 0L, SEEK_SET);
18
19 read_ptr = (unsigned char *)calloc(len, sizeof(unsigned char));
20
21 if(NULL == read_ptr)
22 {
23 puts("Error\n");
24 return 1;
25 }
26 fread(read_ptr, len, 1, p);
27
28 printf("%x %x", *read_ptr, *(read_ptr + 1));
29
30 fwrite(read_ptr, len, 1, f);
31
32 free(read_ptr);
33 fclose(p);
34 fclose(f);
35 return 0;
36 }