关于C语言判断文件尾问题的探讨

前些天心血来潮,准备做一个异或加密工具,用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 

结果这次仔细看了一下,发现了一些小问题.

 

 这条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  * =  fopen(FILE_NAME,  " rb " );
10      FILE  * =  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  }

 

参考文章:http://news.cnblogs.com/n/121416/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值