Fread 和fwrite的参数不同,返回值不同
函数fwrite
刚才编一个关于用C库函数实现的文件复制操作的代码时发生错误。错误的根本是想当然的以为fread函数的用法,对其理解不深刻。后来在网友帮助下才发现错误。
其实函数的用法可以通过Linux中的man来获得帮助。
比如fread.在终端键入
- man 3 fread
这是会出现下面的东西:
- NAME
- fread, fwrite - binary stream input/output
- SYNOPSIS
- #include <stdio.h>
- size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
- size_t fwrite(const void *ptr, size_t size, size_t nmemb,
- FILE *stream);
- DESCRIPTION
- 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.
- 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
- ptr.
- For nonlocking counterparts, see unlocked_stdio(3).
- RETURN VALUE
- 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
- error occurs, or the end of the file is reached, the return value is a short item count (or zero).
- 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.下面给出我的代码,正确实现文件拷贝的代码,以此分析。
- #include <stdio.h>
- #define BUFFER_SIZE 1024
- int main(int argc, char *argv[])
- {
- FILE *from_fp, *to_fp;
- int bytes_read, bytes_write;
- char *ptr;
- char buffer[BUFFER_SIZE];
- if(argc != 3) //参数包括源文件名与目标文件名
- {
- printf("Input failed!\n");
- return 1;
- }
- if( (from_fp = fopen(argv[1],"r")) == NULL ) //以只读方式打开源文件名
- {
- printf("File is not exist\n");
- return 1;
- }
- if((to_fp = fopen(argv[2],"w+")) == NULL) //打开第二个文件
- {
- printf("Open file failed!\n");
- return 1;
- }
- while(bytes_read = fread(buffer, 1, BUFFER_SIZE, from_fp)) //读取BUFFSIZE大小字节
- {
- if(bytes_read > 0) //读取有效数据
- {
- ptr = buffer;
- while(bytes_write = fwrite(ptr, 1, bytes_read, to_fp)) //写数据到目标文件
- {
- if(bytes_write == bytes_read) //写完
- break;
- else if(bytes_write > 0) //未写完
- {
- ptr += bytes_write;
- bytes_read -= bytes_write;
- }
- }
- if(bytes_write == 0) //写错误
- break;
- }
- }
- fclose(from_fp);
- fclose(to_fp);
- return 0;
- }
注 意到我的fread和fwrite中的第二个参数size都是1,这样的话我返回值就是实际读取到的或写入的字节数。刚开始我写的程序不是这样的,我是
- while(bytes_read = fread(buffer, BUFFER_SIZE, 1,from_fp))
- while(bytes_write = fwrite(ptr, bytes_read, 1, to_fp))
这里第三个参数为1,换句话说,也就是说要读取1个元素(返回值为1),此元素中包含BUFFER_SIZE个字节,因为我的文件不满足这个条件,这样的元素值不存在。于是返回的值为0,这也是为什么我的文件数据没有复制到另一个文件的原因了,因为根本就没有执行这个循环中的代码。
另外一个需要注意到的问题是fread函数不能区分文件是否结尾和出错两种情况。所以必须使用ferror()和feof()函数来确定到底是哪种情况,所以关于文件复制还有下面另一种写法。代码如下:
- #include <stdio.h>
- #include <string.h>
- #define BUFFER_SIZE 1024
- int main(int argc, char *argv[])
- {
- FILE *from_fp, *to_fp;
- //int bytes_read, bytes_write;
- long file_len = 0;
- char buffer[BUFFER_SIZE];
- if(argc != 3) //参数包括源文件名与目标文件名
- {
- printf("Input failed!\n");
- return 1;
- }
- if( (from_fp = fopen(argv[1],"r")) == NULL ) //以只读方式打开源文件名
- {
- printf("File is not exist\n");
- return 1;
- }
- if((to_fp = fopen(argv[2],"w+")) == NULL) //打开第二个文件
- {
- printf("Open file failed!\n");
- return 1;
- }
- fseek(from_fp, 0L, SEEK_END); //定位文件指针到尾部
- file_len = ftell(from_fp); //获得文件长度
- fseek(from_fp, 0L, SEEK_SET); //定位文件指针到开始处
- while(!feof(from_fp)) //判断文件是否结束
- {
- fread(buffer, BUFFER_SIZE, 1, from_fp);
- if(BUFFER_SIZE > file_len) //缓冲区长度大于文件长度
- fwrite(buffer, file_len, 1, to_fp);
- else
- {
- fwrite(buffer, BUFFER_SIZE, 1, to_fp);
- file_len -= BUFFER_SIZE;
- }
- bzero(buffer,BUFFER_SIZE); //清零缓冲区
- }
- fclose(from_fp);
- fclose(to_fp);
- return 0;
- }
这里面多了几个函数,其中feof就是用来检测文件是否结尾的函数。其返回值非0时表示文件结束。还有一个函数bzero是清零一段缓冲区的函数,使用需包含头文件string.h。注意fread和fwrite函数的书写就是采用第三个参数为1的方式来书写的了。
Fread 和fwrite的参数不同,返回值不同相关推荐
- Go 学习笔记(61)— Go 高阶函数、函数作为一等公民(函数作为输入参数、返回值、变量)的写法
函数在 Go 语言中属于"一等公民(First-Class Citizen)"拥有"一等公民"待遇的语法元素可以如下使用 可以存储在变量中: 可以作为参数传递给 ...
- EntityCURD操作的参数和返回值
以下是netbeans根据实体自动生成的CURD模板: /** To change this template, choose Tools | Templates* and open the temp ...
- php 函数返回值mixed,认识函数的类型、参数与返回值
函数的类型.参数与返回值 一.函数的基本语法语法 functionfunctionName(类型限定参数列表):返回值类型 { } 案例:计算两个数之和. functionsum(int$a,int$ ...
- C#使用ExecuteReader返回DataReader既有查询结果集又有输出参数或返回值的使用注意事项...
Command 对象公开了几个可用于执行所需操作的 Execute 方法.当以数据流的形式返回结果时,使用 ExecuteReader 可返回 DataReader 对象.使用 ExecuteScal ...
- 反射 -- 业务需求:执行某个类中全部的以test为开头的无参数无返回值的非静态方法。...
package demo; //业务需求:执行某个类中全部的以test为开头的无参数无返回值的非静态方法. import java.lang.reflect.Method; import java.u ...
- 【C++】函数 指针类型参数 与 引用类型参数 对比 ( 修改外部变量需要传入的参数要求 | 参数作返回值 )
文章目录 I . 博客总结 . 指针与引用类型参数 II . 指针作为参数和返回值 III . 引用参数简介 IV . 引用作为参数和返回值 I . 博客总结 . 指针与引用类型参数 1 . 讨论问题 ...
- AOP开发——在不修改源代码的前提下,对类里面的方法进行增强 : 前置 后置 环绕 异常||如何得到目标方法的参数和返回值
AOP开发 @Transactionl 在不修改源代码的前提下,对类里面的方法进行增强 前置 后置 环绕 异常 创建项目前引入aop的包 <dependency> <grou ...
- libsvm中svmtrain的参数和返回值
对svmtrain函数的输入参数和返回值进行说明 1. 训练 libsvm函数用于对训练集的数据进行训练,得到训练好的模型. model = libsvmtrain(training_label_ve ...
- Python基础学习----参数和返回值
# 函数的参数和返回值 # 4种组合方式 # 1.无参无返 # def methodone(): # 2.无参有返 def methodtwo():a=10return a # 3.有参无返 # de ...
- C#多线程函数如何传参数和返回值
提起多线程,不得不提起 委托(delegates)这个概念. 我理解的委托就是 具有 同样参数和返回值 的函数的集合. 比如 public delegate void MyDelegate(int a ...
最新文章
- python中的random模块学习
- JavaScript的写类方式(4)——转
- TTDebug 快速打印 log ------rect point size
- 学习笔记整理之对象的转型
- HDU 1848 Fibonacci again and again(博弈)
- couchdb 自动生成html,如何在CouchDB中使用html模板
- 安卓App热补丁动态修复技术:让App像Web一样发布新版本
- 第三次学JAVA再学不好就吃翔(part106)--字符流
- Java 字符串常用操作(比较、查找位置、删除字符、替换字符串、反向输出、是否存在、分割字符串、大小写转换,区域比较、拼接字符串)
- .Net页面中使用在线编辑框实例
- 如何跨越线程调用窗体控件?(1)
- 利用朴素贝叶斯算法识别垃圾邮件
- IOS快捷指令的用法(快捷指令库使用方法)
- vue项目之页面底部出现白边及空白区域错误记录
- 视网膜眼底图像的一种检测方法,学习笔记(一)
- 有一台服务器可以做哪些很酷的事情
- python kivy 控件(小部件)的属性集合
- 两套工厂通用ERP系统【源代码免费分享】
- C语言开发单片机为什么大多数都采用全局变量的形式?
- 大型电商实战项目,助力2021年高薪
热门文章
- 线性期望(BUPT2015校赛.F)
- mysql left join join right
- AntD 官网样例 InputRef报错原因
- Vue基础学习(一)------内部指令
- hive 中窗口函数row_number,rank,dense_ran,ntile分析函数的用法
- spring mvc拦截器HandlerInterceptor
- imp导入前对当前用户清库脚本
- Rsyslog 日志相关内容
- C语言高级技术之--游戏属性修改器(背景故事)
- 5种ASP.NET页面间传递参数实例代码