Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2764547
  • 博文数量: 505
  • 博客积分: 1552
  • 博客等级: 上尉
  • 技术积分: 2514
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-23 18:24
文章分类

全部博文(505)

文章存档

2019年(12)

2018年(15)

2017年(1)

2016年(17)

2015年(14)

2014年(93)

2013年(233)

2012年(108)

2011年(1)

2009年(11)

分类: LINUX

2016-07-05 22:56:29

转自:http://blog.csdn.net/abclixu123/article/details/8284680
刚才编一个关于用C库函数实现的文件复制操作的代码时发生错误。错误的根本是想当然的以为fread函数的用法,对其理解不深刻。后来在网友帮助下才发现错误。

其实函数的用法可以通过Linux中的man来获得帮助。

比如fread.在终端键入

  1. man 3 fread   
这是会出现下面的东西:
  1. NAME  
  2.        fread, fwrite - binary stream input/output  
  3.   
  4. SYNOPSIS  
  5.        #include   
  6.   
  7.        size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);  
  8.   
  9.        size_t fwrite(const void *ptr, size_t size, size_t nmemb,  
  10.                      FILE *stream);  
  11.   
  12. DESCRIPTION  
  13.        The function fread() reads nmemb elements of data, each size bytes long, from the stream pointed to by stream, storing them at the location given by ptr.  
  14.   
  15.        The  function  fwrite()  writes  nmemb elements of data, each size bytes long, to the stream pointed to by stream, obtaining them from the location given by  
  16.        ptr.  
  17.   
  18.        For nonlocking counterparts, see unlocked_stdio(3).  
  19.   
  20. RETURN VALUE  
  21.        On success, fread() and fwrite() return the number of items read or written.  This number equals the number of bytes transferred only when size is 1.  If an  
  22.        error occurs, or the end of the file is reached, the return value is a short item count (or zero).  
  23.   
  24.        fread() does not distinguish between end-of-file and error, and callers must use feof(3) and ferror(3) to determine which occurred.  

重点放在对返回值。

可以看出,如果调用成功的话,函数会返回读到的元素个数。如果想返回实际读取的字节数的话只有当size=1,也就是第二个参数size为1时。如 果发生读取错误的话,或者已经到达文件末尾,返回值是一个小的元素个数值或者是0.下面给出我的代码,正确实现文件拷贝的代码,以此分析。

  1. #include   
  2.   
  3. #define BUFFER_SIZE  1024  
  4.   
  5. int main(int argc, char *argv[])  
  6. {  
  7.     FILE *from_fp, *to_fp;  
  8.     int bytes_read, bytes_write;  
  9.     char *ptr;  
  10.     char buffer[BUFFER_SIZE];  
  11.   
  12.     if(argc != 3)       //参数包括源文件名与目标文件名  
  13.     {  
  14.         printf("Input failed!\n");  
  15.         return 1;  
  16.     }  
  17.   
  18.     if( (from_fp = fopen(argv[1],"r")) == NULL )    //以只读方式打开源文件名  
  19.     {  
  20.         printf("File is not exist\n");  
  21.         return 1;  
  22.     }  
  23.       
  24.     if((to_fp = fopen(argv[2],"w+")) == NULL)      //打开第二个文件  
  25.     {  
  26.         printf("Open file failed!\n");    
  27.         return 1;  
  28.     }  
  29.   
  30.     while(bytes_read = fread(buffer, 1, BUFFER_SIZE, from_fp))  //读取BUFFSIZE大小字节  
  31.     {  
  32.         if(bytes_read > 0)           //读取有效数据  
  33.         {  
  34.             ptr = buffer;  
  35.             while(bytes_write = fwrite(ptr, 1, bytes_read, to_fp))  //写数据到目标文件  
  36.             {  
  37.                 if(bytes_write == bytes_read)           //写完      
  38.                     break;  
  39.                 else if(bytes_write > 0)         //未写完  
  40.                 {  
  41.                     ptr += bytes_write;  
  42.                     bytes_read -= bytes_write;  
  43.                 }  
  44.             }  
  45.             if(bytes_write == 0)            //写错误  
  46.                 break;  
  47.         }  
  48.     }  
  49.       
  50.     fclose(from_fp);  
  51.     fclose(to_fp);  
  52.   
  53.     return 0;  
  54. }  

注意到我的fread和fwrite中的第二个参数size都是1,这样的话我返回值就是实际读取到的或写入的字节数。刚开始我写的程序不是这样的,我是
  1. while(bytes_read = fread(buffer, BUFFER_SIZE, 1,from_fp))  
  1. while(bytes_write = fwrite(ptr, bytes_read, 1, to_fp))  

这里第三个参数为1,换句话说,也就是说要读取1个元素,此元素中包含BUFFER_SIZE个字节,因为我的文件不满足这个条件,这样的元素值不存在。于是返回的值为0,这也是为什么我的文件数据没有复制到另一个文件的原因了,因为根本就没有执行这个循环中的代码。

另外一个需要注意到的问题是fread函数不能区分文件是否结尾和出错两种情况。所以必须使用ferror()和feof()函数来确定到底是哪种情况,所以关于文件复制还有下面另一种写法。代码如下:

  1. #include   
  2. #include   
  3.   
  4. #define BUFFER_SIZE  1024  
  5.   
  6. int main(int argc, char *argv[])  
  7. {  
  8.     FILE *from_fp, *to_fp;  
  9.     //int bytes_read, bytes_write;  
  10.     long file_len = 0;  
  11.     char buffer[BUFFER_SIZE];  
  12.   
  13.     if(argc != 3)       //参数包括源文件名与目标文件名  
  14.     {  
  15.         printf("Input failed!\n");  
  16.         return 1;  
  17.     }  
  18.   
  19.     if( (from_fp = fopen(argv[1],"r")) == NULL )    //以只读方式打开源文件名  
  20.     {  
  21.         printf("File is not exist\n");  
  22.         return 1;  
  23.     }  
  24.       
  25.     if((to_fp = fopen(argv[2],"w+")) == NULL)      //打开第二个文件  
  26.     {  
  27.         printf("Open file failed!\n");    
  28.         return 1;  
  29.     }  
  30.       
  31.     fseek(from_fp, 0L, SEEK_END);       //定位文件指针到尾部  
  32.     file_len = ftell(from_fp);          //获得文件长度  
  33.     fseek(from_fp, 0L, SEEK_SET);       //定位文件指针到开始处  
  34.   
  35.     while(!feof(from_fp))               //判断文件是否结束  
  36.     {  
  37.         fread(buffer, BUFFER_SIZE, 1, from_fp);  
  38.         if(BUFFER_SIZE > file_len)               //缓冲区长度大于文件长度  
  39.             fwrite(buffer, file_len, 1, to_fp);  
  40.         else                                  
  41.         {  
  42.             fwrite(buffer, BUFFER_SIZE, 1, to_fp);  
  43.             file_len -= BUFFER_SIZE;  
  44.         }  
  45.         bzero(buffer,BUFFER_SIZE);      //清零缓冲区  
  46.     }  
  47.   
  48.     fclose(from_fp);  
  49.     fclose(to_fp);  
  50.   
  51.     return 0;  
  52. }  

这里面多了几个函数,其中feof就是用来检测文件是否结尾的函数。其返回值非0时表示文件结束。还有一个函数bzero是清零一段缓冲区的函数,使用需包含头文件string.h。注意fread和fwrite函数的书写就是采用第三个参数为1的方式来书写的了。
阅读(2088) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~