C编程中fread 、fwrite 用法总结
在C语言中进行文件操作时,我们经常用到fread()和fwrite(),用它们来对文件进行读写操作。下面详细绍一下这两个函数的用法。
我们在用C语言编写程序时,一般使用标准文件系统,即缓冲文件系统。系统在内存中为每个正在读写的文件开辟“文件缓冲区”,在对文件进行读写时数据都经过缓冲区。要对文件进行读写,系统首先开辟一块内存区来保存文件信息,保存这些信息用的是一个结构体,将这个结构体typedef为FILE类型。我们首先要定义一个指向这个结构体的指针,当程序打开一个文件时,我们获得指向FILE结构的指针,通过这个指针,我们就可以对文件进行操作。例如:
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
char buffer[100] = "This is a test";
if((fp = fopen("c:\\example.txt", "w")) == 0)
{
printf("open failed!");
exit(1);
}
fwrite(buffer, 1, strlen("This is a test"), fp);
char a = 'c';
int b =1;
float c = 1.0;
int x = fprintf(fp,"%s%d%f",a,b,c);
printf("c: %d",x);
fclose(fp);
fflush(stdin);
getchar();
return 0;
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
通过以上代码,我们就在c盘的根目录下建立了一个名为example扩展名为.txt的文件,我们打开可以看到上面写上了This is a test。当我们对它将它读出时,用如下代码:
#include <stdio.h>
#include <memory.h>
int main()
{
FILE *fp; int len;
char buffer[100];
/*memset(buffer, 1, 100); */
if((fp = fopen("c:\\example.txt", "r")) == 0)
{
printf("open failed!");
exit(1);
}
fseek(fp, 0L, SEEK_END);
len = ftell(fp);
rewind(fp);
fread(buffer, 1, len , fp);
printf("%s",buffer);
fclose(fp);
getchar();
return (0);
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
可以看到,当我们使用memset了以后,读出了一大堆乱码,这是为什么呢?原因是我们在fwrite函数时写入的字节数是用strlen求得的,也就是说字符串最后的'\0'并没有写到文件中去。所以我们从文件中读到buffer中时也自然没有'\0',因为buffer中的数是随机的,除非buffer中最后一个字符的下一个数恰好随机到0(可能性很小,这里用memset将它排除),否则以%s将buffer中的字符输出时遇不到0,所以乱码产生。解决的办法有很多,你可以在向文件写数据时多写入一个字节,系统会自动写入0,fwrite(buffer, 1, strlen("This is a test")+1, fp);这样读出时最后就有一个0了。或者读出操作完成后,在最后一个字符后面补上一个0:buffer[len] = 0;这样问题也可得到解决。
size_t fread(void *buffer, size_t size, size_t count, FILE *stream);
buffer : 数据存储的地址
size : 要读取的字节的大小
count : 要读取多少个size大小
stream : 等待被读取的数据源,它是一个指向FILE结构的文件指针
fread 如果读取成功,则返回count的大小,如果还没有读取count个size大小的数据时,就以及读取完了整个文件,到了文件结尾的地方了,此时返回的值就要必count小,或者在读取的过程出错的话,返回的值也必count小,所以如果返回的值比count小时,可以通过feof()函数或ferror函数来判断到底是读取过程中出错了还是已经读取到了文件结尾的部分了。 如果size 或count 本身被设置为0, 则fread不做任何操作。
注:fread 函数的功能是从输入流(input stream)中读取count个size大小的字节数存储到buffer中,关联输入流的文件指针的位置会随着字节数的读取而向前移动。如果输入流是以文本模式打开的,那么单个换行符将会被替换成回车换行符,换行符的替换,不会影响到文件指针和返回值。如果遇到了错误,那么文件指针的当前位置和已读取的不部分值都是不确定的。
size_t fwrite(const void *buffer, size_t size, size_t count , FILE *stream)
buffer: 指向被写入的数据源指针
size: 每次写入的字节数大小
count : 执行一次fwrite函数,最大可写入 count个size大小的字节数
stream 指向等待写入数据的文件指针,即文件被写入的地址
如果写入成功则返回count值。
fwrite的功能是将文件从buffer中写入到output stream中去,每次写入的字节数为size, 最多可写入count次。
下面通过一个example 来进一步说明fread和fwrite的用法
/* FREAD.C: This program opens a file named FREAD.OUT and
* writes 25 characters to the file. It then tries to open
* FREAD.OUT and read in 25 characters. If the attempt succeeds,
* the program displays the number of actual items read.
*/
#include <stdio.h>
void main( void )
{
FILE *stream;
char list[30];
int i, numread, numwritten;
/* Open file in text mode: */
if( (stream = fopen( "fread.out", "w+t" )) != NULL )
{
for ( i = 0; i < 25; i++ )
list[i] = (char)('z' - i);
/* Write 25 characters to stream */
numwritten = fwrite( list, sizeof( char ), 25, stream );
printf( "Wrote %d items\n", numwritten );
fclose( stream );
}
else
printf( "Problem opening the file\n" );
if( (stream = fopen( "fread.out", "r+t" )) != NULL )
{
/* Attempt to read in 25 characters */
numread = fread( list, sizeof( char ), 25, stream );
printf( "Number of items read = %d\n", numread );
printf( "Contents of buffer = %.25s\n", list );
fclose( stream );
}
else
printf( "File could not be opened\n" );
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Output Wrote 25 items Number of items read = 25 Contents of buffer = zyxwvutsrqponmlkjihgfedcb
|
fread 和fwrite函数
函数功能:用来读写一个数据块
一般调用形式:
size_t fread(buffer, size , count, fp);
size_t fwrite(buffer, size , count , fp);
参数说明:
(1)buffer: 是一个指针,对fread来说,它是读入数据的存放地址,对fwrite来说,是要输出的数据的地址。
(2)size: 一次要读写的字节数(即fread 或fwrite 执行读或写的过程中,一次读/写的字节数大小为size个)
(3)count: 最多读写多少个size字节的数据(即调用一次fread或fwrite,它们在执行读/写的过程中,最多可以执行count次读/写操作,每次只能读/写size个字节大小的数据,为什么说最多可执行count次呢?比如希望调用fread()这条语句读取K大小的数据,如果fread()中的size参数比K要小,那么就要多读几次才能读取K大小的数据,这时我们就设置要读取count次,那么最多可读取count* size个字节大小的数据,但是这个count*size 不可能刚好是K的整数倍啊,这样它必定是(count-i)*size + x = K, 这里的i 肯定是大于等于1的自然数,而x是小size且大于0的自然数,那么这样到读取完K大小的字节数还不需要执行count次操作。所以说最多执行count次)
(4)fp: FILE 型指针变量
注意:
1.完成一次写操作(fwrite())后必须关闭流(fclose());
2.完成一次读操作(fread())后,如果没有关闭流(fclose()),则指针(FILE *fp)自动向后移动前一次读写的长度,不关闭流继续下一次读操作则接着上次的输出继续输出。(例如stream = "12345678不关闭流接着输出", 通过fread() 读出到12345678就没有读取了,此时fp指针就指向了"8"这个位置,此时忘记关闭去流,那么下次还是用fp这个指针再通过fread()来读取的话,那么此时的输出是从"不"字开始输出"不关闭流…",而不是从"1"开始输出"12345678不关闭…")
fwrite和fread的应用举例:
1.将一个字符串写入文件:
char *str="hello,I am a test program!";
fwrite(str,sizeof(char),strlen(str),fp)
2.将一个字符数组写入文件:
char str[]={'a','b','c','d','e'};
fwrite(str,sizeof(char),sizeof(str),fp)
3.将一个整型数组写入文件:
int a[]={12,33,23,24,12};
先计算数组元素个数nmemb,之后
fwrite(a,sizeof(int),nmemb,fp)
read/write 和 fread/fwrite 有什么区别
实现机制是什么,两者有什么联系,对文件读写,两者那个效率更高,速度更快
举个例子:
如果文件的大小是8k。
你如果用read/write,且只分配了2k的缓存,则要将此文件读出需要做4次系统调用来实际从磁盘上读出。
如果你用fread/fwrite,则系统自动分配缓存,则读出此文件只要一次系统调用从磁盘上读出。
也就是用read/write要读4次磁盘,而用fread/fwrite则只要读1次磁盘。效率比read/write要高4倍。
如果程序对内存有限制,则用read/write比较好。
一般用来处理文件
都用fread 和fwrite,它自动分配缓存,速度会很快,比自己来做要简单
如果要处理一些特殊的描述符,用read 和write,如套接口,管道之类的
C编程中fread 、fwrite 用法总结的更多相关文章
- Shell编程中Shift的用法
Shell编程中Shift的用法 位置参数可以用shift命令左移.比如shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1.$2.$3丢弃,$0不移动.不带参数的shif ...
- Shell编程中Shift的用法【转】
本文转载自:http://www.cnblogs.com/image-eye/archive/2011/08/20/2147153.html Shell编程中Shift的用法 位置参数可以用shift ...
- 详解shell编程中2>&1用法
在使用 linux 命令或者 shell 编程时,这个用法常会遇到 2>&1 下面看一个命令示例,然后分析下他是如何工作的: ls foo > /dev/null 2>&am ...
- shell编程中的select用法
select 语句 select表达式是bash的一种扩展应用,擅长于交互式场合.用户可以从一组不同的值中进行选择: select var in ... ; do break; done .... n ...
- bash 编程中循环语句用法
1.if 是单分支语句,使用格式如下: if condition ; then statement ….. fi 2.if … else 是双分支语句,使用格式如下: if condition ; t ...
- Shell编程中Shift的用法(转)
位置参数可以用shift命令左移.比如shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1.$2.$3丢弃,$0不移动.不带参数的shift命令相当于shift 1. 非常 ...
- Shell编程中while与for的区别及用法详解【转】
在shell编程中经常用到循环,常用的循环有for和while循环两种.while循环默认以行读取文件,而for循环以空格读取文件切分文件,本篇就结合现网的一些使用示例说说二者的用法和区别. 一.常用 ...
- (转)轻松掌握shell编程中数组的常见用法及示例
缘起:在老男孩进行linux培训shell编程教学中,发现不少水平不错的网友及同学对数组仍然很迷糊,下面就给大家分享下数组的用法小例子,希望能给大家一点帮助.其实SHELL的数组很简单,好用.我们学习 ...
- shell编程系列21--文本处理三剑客之awk中数组的用法及模拟生产环境数据统计
shell编程系列21--文本处理三剑客之awk中数组的用法及模拟生产环境数据统计 shell中的数组的用法: shell数组中的下标是从0开始的 array=("Allen" & ...
随机推荐
- pygame试水,写一个贪吃蛇
最近学完python基础知识,就想着做一个游戏玩玩,于是就在https://www.pygame.org/docs/学着做了个贪吃蛇游戏. 首先要导入模块. import pygame import ...
- ASP.NET MVC中如何在客户端进行必要的判断
背景:在开发网站时,往往需要对用户的输入进行合法性检查,如果验证工作都放在服务器端,势必将影响网页的响应速度,同时给用户不好的体验.本篇随笔即是使用JQuery在客户端进行必要的合法检测. JS代码如 ...
- 大数据学习——linux常用命令(二)
二.目录操作 1 查看目录信息 ls / 查看根目录下的文件信息 ls . 或者 ls ./查看当前目录下的文件信息 ls ../查看根目录下 ls /home/hadoop ls -l . 查看当前 ...
- 1284-Primitive Roots,学信安的路过
Primitive Roots 此题通过率如此之高,料想不会很难,但是再简单小菜还是不会.. 嗯,下 ...
- Archiving not possible: No primary destinations errors
If space ran out in an archive destination, after you fix the problem, you may still recieve the fol ...
- 从零到一,使用实时音视频 SDK 一起开发一款 Zoom 吧
zoom(zoom.us) 是一款受到广泛使用的在线会议软件.相信各位一定在办公.会议.聊天等各种场景下体验或者使用过,作为一款成熟的商业软件,zoom 提供了稳定的实时音视频通话质量,以及白板.聊天 ...
- GO 语言周报【七月第 1 期】
TIOBE 七月排名 Go 进入前十 TIOBE 七月头条:Go 语言达到历史最高并进入前十.对于 Go 语言来说,这是一个里程碑时刻,我们可以更大胆地想象,它下一步的发展会达到怎样的高度.Go 是否 ...
- android GET 请求在5.0版本的取不到数据,报IO异常兼容问题解决
使用lib类库xUtils-2.6.10.jar作为数据请求的框架,在android的5.0版会有兼容问题,取不到GET请求的数据. 但是POST没有问题,难取到数据. public static R ...
- 匿名函数--lambda函数
匿名函数 匿名函数:为了解决一些功能很简单的需求而设计的一句话函数 (python对匿名函数支持有限,只有一些简单的条件下可以用匿名函数) 匿名函数固定格式: func = lambda *args: ...
- .htaccess重写、安全防护、文件访问权限
今天在<外刊IT评论>上看见了关于.htaccess的使用总结,觉得很不错的,因为wp博客还有其他的php的web服务站点好多都是用.htaccess来管理比如效率以及安全的问题,有必要来 ...