Fread 和fwrite的参数不同,返回值不同

函数fwrite

功能
  C语言函数,向文件写入一个数据块  。
size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
注意:这个函数以二进制形式对文件进行操作,不局限于文本文件
返回值:返回实际写入的数据块数目
(1)buffer:是一个指针,对fwrite来说,是要输出数据的地址;
(2)size:要写入内容的单字节数;
(3)count:要进行写入size字节的数据项的个数;
(4)stream:目标文件指针;
(5)返回实际写入的数据项个数count。



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

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

比如fread.在终端键入

[cpp] view plaincopyprint?
  1. man 3 fread   
这是会出现下面的东西:
[cpp] view plaincopyprint?
  1. NAME  
  2.        fread, fwrite - binary stream input/output  
  3.   
  4. SYNOPSIS  
  5.        #include <stdio.h>  
  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.下面给出我的代码,正确实现文件拷贝的代码,以此分析。

[cpp] view plaincopyprint?
  1. #include <stdio.h>  
  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,这样的话我返回值就是实际读取到的或写入的字节数。刚开始我写的程序不是这样的,我是
[cpp] view plaincopyprint?
  1. while(bytes_read = fread(buffer, BUFFER_SIZE, 1,from_fp))  
[cpp] view plaincopyprint?
  1. while(bytes_write = fwrite(ptr, bytes_read, 1, to_fp))  

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

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

[cpp] view plaincopyprint?
  1. #include <stdio.h>  
  2. #include <string.h>  
  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的方式来书写的了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/253063.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

课程简介及算法分析

先学课程 -概率论 运行时间&#xff08;running time&#xff09; - 输入&#xff08;eg 已经排序&#xff09; - 输入规模&#xff08;6和6*10^9&#xff09; 各种各样的分析&#xff1a; - 最坏情况分析&#xff08;worst case&#xff09;usually T(n) max time when inp…

利用shell脚本添加环境变量

在shell脚本设置了环境变量&#xff0c;如export LIBRARY_PATH./lib/&#xff0c;执行了此脚本后, 在执行生成的可执行文件&#xff0c;提示错误 error while loading shared libraries: libww.so: cannot open shared object file: No such file or directory 但是如果把expor…

2017 ACM-ICPC西安网赛B-Coin

B-Coin Bob has a not even coin, every time he tosses the coin, the probability that the coins front face up is \frac{q}{p}(\frac{q}{p} \le \frac{1}{2})​p​​q​​(​p​​q​​≤​2​​1​​). The question is, when Bob tosses the coin kktimes, whats the pr…

Java第四次作业

Dog dognew Dog("哈士奇","黑白",2);System.out.println(dog);}}class Dog {private String name;private String color;private int age;public String getName(){return name;}public String getColor(){return color;}public int getAge(){return age;}…

ITU-RBT.656视频标准接口

601是SDTV的数据结构 656是SDTV的interface 709是HDTV的数据结构 1120是HDTV的interface ITU-R BT.601是演播室数字电视编码参数标准&#xff0c;而ITU-R BT.656 则是ITU-R BT.601附件A中的数字接口标准&#xff0c; 用于主要数字视频设备(包括芯片)之间采用27Mhzs并口或243Mb…

C语言博客作业03--函数

1.本章学习总结 1.1思维导图 1.2本章学习体会及代码量学习体会 1.2.1学习体会 本周学习了函数&#xff0c;其实&#xff0c;函数于之前学习的三大控制结构是密不可分的&#xff0c;而函数又有其特殊的地方&#xff0c;例如&#xff1a;函数的声明、函数的调用等等。我们之前编写…

Shell记录-Shell命令(其他)

top命令是Linux下常用的性能分析工具&#xff0c;能够实时显示系统中各个进程的资源占用状况&#xff0c;类似于Windows的任务管理器。 &#xff0e;命令格式 top [参数]Shell2&#xff0e;命令功能 显示当前系统正在执行的进程的相关信息&#xff0c;包括进程ID、内存占用率、…

Insta360:从软到硬,一年做出360°全景相机,中间填了多少坑?

摘要刘靖康在大学就开始创业。在大二的时候他曾经去腾讯实习&#xff0c;然后又去了“超级课程表”这个团队实习半年&#xff0c;2013 年 9 月回到南京创业&#xff0c;一开始的产品叫“名校直播”&#xff0c;是一款围绕院校名师讲座所做的视频直播产品。 不久前&#xff0c;一…

No.10 awk、变量、运算符、if多分支

awk、变量、运算符、if多分支 awk语法 ~ awk -F: {print $3,$4} /etc/passwd //-F指定:分隔符 默认以空格作为分隔符 ~ awk -F: {print &0,NF} //$0打印全部,NF有几段内容 ~ awk -F: {print $NF} /etc/passwd //$NF打印最后一段内容 ~ awk -F: {print NR} /etc/passwd…

什么是自然语言处理技术

自然语言处理&#xff08;NLP&#xff09;是计算机科学&#xff0c;人工智能&#xff0c;语言学关注计算机和人类&#xff08;自然&#xff09;语言之间的相互作用的领域。自然语言处理是计算机科学领域与人工智能领域中的一个重要方向。它研究能实现人与计算机之间用自然语言进…

SDOI2005 区间

题目描述 现给定n个闭区间[ai, bi]&#xff0c;1<i<n。这些区间的并可以表示为一些不相交的闭区间的并。你的任务就是在这些表示方式中找出包含最少区间的方案。你的输出应该按照区间的升序排列。这里如果说两个区间[a, b]和[c, d]是按照升序排列的&#xff0c;那么我们有…

排序: 选择排序

1. 基本原理 将待排序的元素分为已排序(初始为空)和未排序两组&#xff0c;依次将未排序的元素中值最小的元素放入已排序的组中。 直接选择排序简单直观&#xff0c;但性能略差&#xff1b;堆排序是一种较高效的选择排序方法&#xff0c;但实现起来略微复杂。 2. 直接选择排序 …

JavaScript的值传递和引用传递

原文: Explaining Value vs. Reference in Javascript译者: Fundebug为了保证可读性&#xff0c;本文采用意译而非直译。另外&#xff0c;本文版权归原作者所有&#xff0c;翻译仅用于学习。 JavaScript有5种基本的数据类型&#xff0c;分别是&#xff1a;布尔、null、undefine…

全景摄像技术大有可为

网络摄像机发展至今&#xff0c;已经基本满足了“高清”、“日夜监控”、“远距离监控”的需求&#xff0c;但是 随着细分市场的发展&#xff0c;超广角摄像机需求逐渐凸显出来。主要应用在会议室、办公室、大厅/大堂、商场、仓库、车间等大面积开阔的区域&#xff0c;解决原来…

C#编程(五十三)----------字典DictionaryTKey,TValue

字典 关键字:Dicitionary 说明: 必须包含命名空间System.Collection.Generic Dictionary里面的每一个元素都是一个键值对(由两个元组组成:键和值). 键必须是唯一的,而值不需要唯一的. 键和值都可以是任意类型(例如:string,int,自定义类型,等等) 通过一个键读取一个值的事件是接…

setInterval只执行一次的原因

1 setInterval(arrow(),2000) 改为&#xff1a; 1 setInterval(arrow,2000) 原因&#xff1a; arrow()这是一个函数调用&#xff0c;函数调用就会有返回值&#xff0c; 而arrow()没有返回值&#xff0c;所以这里的arrow()是一个undefined&#xff0c;自然你想要的循环执行arrow…

java文件传输之文件编码和File类的使用

---恢复内容开始--- 我们知道&#xff0c;在用户端和服务端之间存在一个数据传输的问题&#xff0c;例如下载个电影、上传个照片、发一条讯息。在这里我们 就说一下文件的传输。 1.文件编码 相信大家小时候玩过积木&#xff08;没玩过也看过吧&#xff09;&#xff0c;看到一个…

Android 模拟输入那点事

因工作原因&#xff0c;需要用到模拟输入这个东东&#xff0c;查阅了一些资料&#xff0c;实现方式有多种&#xff0c;我大概分为两类&#xff0c;命令行类和程序类。 命令行类包括自动化测试组件monkeyrunner&#xff0c;getevent/setevent命令&#xff0c;input命令 程序类包…

arm-linux-gcc:Command not found的问题

标签&#xff1a; ubuntulinux 2015-05-15 10:47 680人阅读 评论(0) 收藏 举报 分类&#xff1a; Ubuntu&#xff08;23&#xff09; /etc/profile gcc&#xff08;9&#xff09; ARM汇编指令&#xff08;4&#xff09; 折腾了一天&#xff0c;终于搞定了。 ubuntu没有roo…

[No0000111]java9环境变量配置bat

保存成bat&#xff08;utf-8 无签名 编码&#xff09; 右键以管理员权限运行 修改JAVAINSTALLPATH 为JAVA SDK 安装目录&#xff08;默认用C:\PROGRAM FILES\JAVA\&#xff09;即可&#xff1b; 只在 用户变量下 创建&#xff0c;会事先保存好用户原有的“JAVA_HOME,JRE_HOME,P…