前些天心血来潮,准备做一个异或加密工具,用Java写了一个,感觉不过瘾.Java这东西还要依靠虚拟机运行.所以,准备再用C语言实现一遍.
还是参考HP UX的CP命令代码,如下:
HP UX CP
1
#include
<
stdio.h
>
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
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则会多读取一次.
在此之前,我的师兄王晔用判断文件大小的方法复制文件,对小文件的操作或许可以采用.
附师兄的源码:
Wang Ye copy
1
#include
<
stdio.h
>
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 }
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 }