函数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. SYNOPSIS
  4. #include <stdio.h>
  5. size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
  6. size_t fwrite(const void *ptr, size_t size, size_t nmemb,
  7. FILE *stream);
  8. DESCRIPTION
  9. 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.
  10. 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
  11. ptr.
  12. For nonlocking counterparts, see unlocked_stdio(3).
  13. RETURN VALUE
  14. 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
  15. error occurs, or the end of the file is reached, the return value is a short item count (or zero).
  16. 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. #define BUFFER_SIZE  1024
  3. int main(int argc, char *argv[])
  4. {
  5. FILE *from_fp, *to_fp;
  6. int bytes_read, bytes_write;
  7. char *ptr;
  8. char buffer[BUFFER_SIZE];
  9. if(argc != 3)       //参数包括源文件名与目标文件名
  10. {
  11. printf("Input failed!\n");
  12. return 1;
  13. }
  14. if( (from_fp = fopen(argv[1],"r")) == NULL )    //以只读方式打开源文件名
  15. {
  16. printf("File is not exist\n");
  17. return 1;
  18. }
  19. if((to_fp = fopen(argv[2],"w+")) == NULL)      //打开第二个文件
  20. {
  21. printf("Open file failed!\n");
  22. return 1;
  23. }
  24. while(bytes_read = fread(buffer, 1, BUFFER_SIZE, from_fp))  //读取BUFFSIZE大小字节
  25. {
  26. if(bytes_read > 0)           //读取有效数据
  27. {
  28. ptr = buffer;
  29. while(bytes_write = fwrite(ptr, 1, bytes_read, to_fp))  //写数据到目标文件
  30. {
  31. if(bytes_write == bytes_read)           //写完
  32. break;
  33. else if(bytes_write > 0)         //未写完
  34. {
  35. ptr += bytes_write;
  36. bytes_read -= bytes_write;
  37. }
  38. }
  39. if(bytes_write == 0)            //写错误
  40. break;
  41. }
  42. }
  43. fclose(from_fp);
  44. fclose(to_fp);
  45. return 0;
  46. }

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

这里面多了几个函数,其中feof就是用来检测文件是否结尾的函数。其返回值非0时表示文件结束。还有一个函数bzero是清零一段缓冲区的函数,使用需包含头文件string.h。注意fread和fwrite函数的书写就是采用第三个参数为1的方式来书写的了。

Fread 和fwrite的参数不同,返回值不同相关推荐

  1. Go 学习笔记(61)— Go 高阶函数、函数作为一等公民(函数作为输入参数、返回值、变量)的写法

    函数在 Go 语言中属于"一等公民(First-Class Citizen)"拥有"一等公民"待遇的语法元素可以如下使用 可以存储在变量中: 可以作为参数传递给 ...

  2. EntityCURD操作的参数和返回值

    以下是netbeans根据实体自动生成的CURD模板: /** To change this template, choose Tools | Templates* and open the temp ...

  3. php 函数返回值mixed,认识函数的类型、参数与返回值

    函数的类型.参数与返回值 一.函数的基本语法语法 functionfunctionName(类型限定参数列表):返回值类型 { } 案例:计算两个数之和. functionsum(int$a,int$ ...

  4. C#使用ExecuteReader返回DataReader既有查询结果集又有输出参数或返回值的使用注意事项...

    Command 对象公开了几个可用于执行所需操作的 Execute 方法.当以数据流的形式返回结果时,使用 ExecuteReader 可返回 DataReader 对象.使用 ExecuteScal ...

  5. 反射 -- 业务需求:执行某个类中全部的以test为开头的无参数无返回值的非静态方法。...

    package demo; //业务需求:执行某个类中全部的以test为开头的无参数无返回值的非静态方法. import java.lang.reflect.Method; import java.u ...

  6. 【C++】函数 指针类型参数 与 引用类型参数 对比 ( 修改外部变量需要传入的参数要求 | 参数作返回值 )

    文章目录 I . 博客总结 . 指针与引用类型参数 II . 指针作为参数和返回值 III . 引用参数简介 IV . 引用作为参数和返回值 I . 博客总结 . 指针与引用类型参数 1 . 讨论问题 ...

  7. AOP开发——在不修改源代码的前提下,对类里面的方法进行增强 : 前置 后置 环绕 异常||如何得到目标方法的参数和返回值

    AOP开发 @Transactionl 在不修改源代码的前提下,对类里面的方法进行增强 前置 后置 环绕 异常 创建项目前引入aop的包 <dependency>     <grou ...

  8. libsvm中svmtrain的参数和返回值

    对svmtrain函数的输入参数和返回值进行说明 1. 训练 libsvm函数用于对训练集的数据进行训练,得到训练好的模型. model = libsvmtrain(training_label_ve ...

  9. Python基础学习----参数和返回值

    # 函数的参数和返回值 # 4种组合方式 # 1.无参无返 # def methodone(): # 2.无参有返 def methodtwo():a=10return a # 3.有参无返 # de ...

  10. C#多线程函数如何传参数和返回值

    提起多线程,不得不提起 委托(delegates)这个概念. 我理解的委托就是 具有 同样参数和返回值 的函数的集合. 比如 public delegate void MyDelegate(int a ...

最新文章

  1. python中的random模块学习
  2. JavaScript的写类方式(4)——转
  3. TTDebug 快速打印 log ------rect point size
  4. 学习笔记整理之对象的转型
  5. HDU 1848 Fibonacci again and again(博弈)
  6. couchdb 自动生成html,如何在CouchDB中使用html模板
  7. 安卓App热补丁动态修复技术:让App像Web一样发布新版本
  8. 第三次学JAVA再学不好就吃翔(part106)--字符流
  9. Java 字符串常用操作(比较、查找位置、删除字符、替换字符串、反向输出、是否存在、分割字符串、大小写转换,区域比较、拼接字符串)
  10. .Net页面中使用在线编辑框实例
  11. 如何跨越线程调用窗体控件?(1)
  12. 利用朴素贝叶斯算法识别垃圾邮件
  13. IOS快捷指令的用法(快捷指令库使用方法)
  14. vue项目之页面底部出现白边及空白区域错误记录
  15. 视网膜眼底图像的一种检测方法,学习笔记(一)
  16. 有一台服务器可以做哪些很酷的事情
  17. python kivy 控件(小部件)的属性集合
  18. 两套工厂通用ERP系统【源代码免费分享】
  19. C语言开发单片机为什么大多数都采用全局变量的形式?
  20. 大型电商实战项目,助力2021年高薪

热门文章

  1. 线性期望(BUPT2015校赛.F)
  2. mysql left join join right
  3. AntD 官网样例 InputRef报错原因
  4. Vue基础学习(一)------内部指令
  5. hive 中窗口函数row_number,rank,dense_ran,ntile分析函数的用法
  6. spring mvc拦截器HandlerInterceptor
  7. imp导入前对当前用户清库脚本
  8. Rsyslog 日志相关内容
  9. C语言高级技术之--游戏属性修改器(背景故事)
  10. 5种ASP.NET页面间传递参数实例代码