C语言文件操作之文件的读写1文档格式.docx
《C语言文件操作之文件的读写1文档格式.docx》由会员分享,可在线阅读,更多相关《C语言文件操作之文件的读写1文档格式.docx(18页珍藏版)》请在冰豆网上搜索。
当文件按指定的工作方式打开以后,就可以执行对文件的读和写。
下面按文件的性质分类进行操作。
对文本文件来说,可按字符读写或按字符串读写;
对二进制文件来说,可进行成块的读写或格式化的读写。
1.读写字符
C提供fgetc和fputc函数对文本文件进行字符的读写,其函数的原型存于stdio.h头文件中,格式为:
intfgetc(FILE*stream)
fgetc()函数从输入流的当前位置返回一个字符,并将文件指针指示器移到下一个字符处,如果已到文件尾,函数返回EOF,此时表示本次操作结束,若读写文件完成,则应关闭文件。
intfputc(intch,FILE*stream)
fputc()函数完成将字符ch的值写入所指定的流文件的当前位置处,并将文件指针后移一位。
fputc()函数的返回值是所写入字符的值,出错时返回EOF。
[例8-2]将存放于磁盘的指定文本文件按读写字符方式逐个地从文件读出,然后再将其显示到屏幕上。
采用带参数的main(),指定的磁盘文件名由命令行方式通过键盘给定。
#include<
main(intargc,char*argv[])
charch;
FILE*fp;
inti;
if((fp=fopen(argv[1],"
r"
))==NULL)/*打开一个由argv[1]所指的文件*/
notopen"
exit(0);
while((ch=fgetc(fp))!
=EOF)/*从文件读一字符,显示到屏幕*/
putchar(ch);
fclose(fp);
程序是一带参数的main()函数,要求以命令行方式运行,其参数argc是用于记录输入参数的个数,argv是指针数组,用于存放输入参数的字符串,串的个数由argc描述。
假设我们指定读取的文件名为L8-2.c,并且列表文件内容就是源程序。
经过编译和连接生成可执行的文件L8-2.exe。
运行程序l8-2.exe,输入的命令行方式为:
c:
\tc>
l8-2L8-2.c
上述程序以命令行方式运行,其输入参数字符串有两个,即argv[0]="
l8-2"
、argv[1]="
L8-2.c"
,argc=2。
故打开的文件是L8-2.c。
程序中对fgetc()函数的返回值不断进行测试,若读到文件尾部或读文件出错,都将返回C的整型常量EOF,其值为非零有效整数。
程序的运行输出为源程序本身:
#include<
))==NULL)/*打开一个由argv[1]所指的文件*/
[例8-3]从键盘输入字符,存到磁盘文件1.txt中:
给出原文件代码换成图片亲自运行后有误,所以附上自己调适的代码
自己调试的代码
stdlib.h>
intmain()
/*定义文件变量指针*/
if((fp=fopen("
1.txt"
"
w"
))==NULL)/*以只写方式打开文件*/
cannotopenfile!
\n"
while((ch=fgetchar())!
='
\n'
)/*只要输入字符非回车符*/
fputc(ch,fp);
/*写入文件一个字符*/
程序通过从键盘输入一以回车结束的字符串,写入指定的流文件1.txt,文件以文本只写方式打开,所以流文件具有可读性,能支持各种字符处理工具访问。
简单地说,我们可以通过DOS提供的type命令来列表显示文件内容。
运行程序:
hello,iloveyou
在DOS操作系统环境下,利用type命令显示1.txt文件如下:
\>
type1.txt
2.读写字符串
C提供读写字符串的函数原型在stdio.h头文件中,其函数形式为:
Char*fgets(char*str,intnum,FILE*stream)
fgets()函数从流文件stream中读取至多num-1个字符,并把它们放入str指向的字符数组中。
读取字符直到遇见回车符或EOF(文件结束符)为止,或读入了所限定的字符数。
intfputs(char*str,FILE*stream)
fputs()函数将str指向的字符串写入流文件。
操作成功时,函数返回0值,失败返回非零值。
[例8-4]向磁盘写入字符串,并写入文本文件test.txt:
string.h>
main()
charstr[128];
if((fp=fopen("
test.txt"
))==NULL)/*打开只写的文本文件*/
while((strlen(gets(str)))!
=0)
{/*若串长度为零,则结束*/
fputs(str,fp);
/*写入串*/
fputs("
fp);
/*写入回车符*/
/*关文件*/
运行该程序,从键盘输入长度不超过127个字符的字符串,写入文件。
如串长为0,即空串,程序结束。
输入:
Hello!
Howdoyoudo
Good-bye!
运行结束后,我们利用dos的type命令列表文件:
typetest.txt
这里所输入的空串,实际为一单独的回车符,其原因是gets函数判断串的结束是以回车作标志的。
[例8-5]从一个文本文件1.txt中读出字符串,再写入另一个文件2.txt。
C语言文件读写练习_一个文件复制程序
阅读
这几天浏览了很多人的博客,发现似乎有这么个规律:
大神的blog中代码很少甚至没有一行代码,且大多是写一些认真思考出来的东西,而像我这样的新手blog好多都是"
贴代码"
,有时候连两句"
废话"
都懒得扯。
正文
这次整理的是我第一次用C写的文件复制程序。
那时候为了理解
流(Stream)
这个东西也算是费了心思了,印象最深刻的便是把流比作管道,数据通过管道流通。
到现在也不敢说完全理解,对新手而言,抽象的概念远不如具体的代码让人安心。
对这些抽象的概念,我的一点点体会就是,
一时不能理解没什么关系,多写代码体验一下,多思考,慢慢的也就悟出来了
旧文中是按文本流复制的,如果仅仅是复制文本文件还行,
但是如果想要复制非文本文件,可能会出现问题。
经测试,即使文件打开方式是"
rb"
wb"
也不能正常复制exe文件,原因应该在那个while循环上了。
因此这次改成以二进制流的形式复制。
这样应该能用于所有类型的文件。
旧文中是一次复制一个字符,一般来说,这样的效率不高。
就像上一篇
[旧文整理]打印所有真值组合的练习题,整理并改进
中那样,频繁地调用IO函数,性能损失特别大。
所以这次同样尝试使用"
缓存"
,我的方案是使用fread()
和fwrite()函数按字节块复制。
重新写的程序代码还是要贴出来的,呵呵:
?
/*******************
*CopyFile:
此函数用于复制指定的文件到指定的位置,
*
功能算是Windows下的copy,或linux下的cp.
*这里的实现用了fread()和fwrite(),二进制流的形式读写
*返回值:
非负数:
复制的字节数.
小于0的数:
请检查文件名是否正确输入,是否合法.
*******************/
longCopyFile(constchar*file_1,constchar*file_2)
FILE*pfRead=fopen(file_1,"
//pfRead用作复制源.
FILE*pfWrite=fopen(file_2,"
//pfWrite对应复制出来的新文件.
if(NULL==pfRead||NULL==pfWrite)
fclose(pfRead);
fclose(pfWrite);
return-1;
longbytesCount=0;
//统计复制的字节数.long最大可以表示不超过2GB的文件
/*因为C没有byte类型,所以这里用char替代
*貌似对大多数机器来说,char都是单字节
*/
intarrLen=1024;
//这个是缓存数组的元素大小
charbufArr[arrLen];
//这个是"
缓存的字节数是elementSize*arrLen.
intcopiedLen;
//这个变量用来记录fread函数每一次真正读取的元素数
intelementSize=sizeof(bufArr[0]);
do
copiedLen=0;
copiedLen=fread(bufArr,elementSize,arrLen,pfRead);
fwrite(bufArr,elementSize,copiedLen,pfWrite);
bytesCount+=copiedLen*elementSize;
}while(copiedLen==arrLen);
//关闭流.
returnbytesCount;
/*此程序从命令行参数获取文件名(路径):
C:
application_namefile1_namefile2_name
*Example:
cfilecopy.exee:
\abc.txtf:
\abc2.txt
*abc.txt必须存在,abc2.txt可以不存在,会自动创建文件.
*如果abc2.txt已存在,会被覆盖掉.
(友情提示:
注意保存重要的文件,别被"
盖"
了!
)
**/
intmain(intargc,char*argv[])
if(argc==3)
char*f1=argv[1];
char*f2=argv[2];
CopyFile1:
%s\nToFile2:
%s\n"
f1,f2);
puts("
Copying......"
longbytesCount=CopyFile(f1,f2);
if(bytesCount<
0)
Failtocopy."
else
%ldbyteswroteinto%s.\n"
bytesCount,f2);
parameterserror"
//getchar();
return0;
这个是stdio.h头文件中的声明:
/*
*DirectInputandOutputFunctions
*/
_CRTIMPsize_t__cdecl__MINGW_NOTHROWfread(void*,size_t,size_t,FILE*);
_CRTIMPsize_t__cdecl__MINGW_NOTHROWfwrite(constvoid*,size_t,size_t,FILE*);
当我看到fread()
和fwrite()的声明,并且了解各个参数的含义之后,我就有了一个问题:
数组的类型,int和char或者其他类型会对函数的执行有什么影响?
有这个问题,是因为我不清楚fread()
和fwrite()的工作方式,如果他们是一次读写一个相应类型大小的字节块,那么用不同的类型性能可能就会不一样。
不过经过测试(测试时分别用了char
和int,调整arrLen,保证数组的字节大小是一样的,即如果是
intbufArr[256],那么相应的有
charbufArr[1024]做对比),我并没有发现类型对性能有什么明显影响。
对性能的影响主要反映在缓存的字节大小上。
为了验证复制出来文件与源文件是否一样,我找了个文件指纹校验软件比较生成的MD5值。
结果显示复制出的文件和源文件是完全一样的<
^_^>
。
找了一个大约17.5MB的文本文件(用记事本打开巨卡)。
使用旧版的程序复制文本文件,测试三次:
2.059s,2.057s,2.057s。
改进过的程序,当缓存设置为1字节时:
2.126s,2.118s,2.113s。
这个相当于一次复制一个字节,还不如旧版的呢。
当缓存设置为2字节时:
1.095s,1.075s,1.101s。
优势体现出来了
当缓存设置为4字节时:
0.572s,0.579s,0.574s。
性能几乎是线性提高。
当缓存设置为8字节时:
0.322s,0.355s,0.320s。
提升幅度开始下降了,常数时间的影响越来越明显。
直接把缓存设置为512字节:
0.062s,0.068s,0.062s。
性能已经非常好了。
继续加大缓存,性能没有任何提高了,这个时候物理磁盘的速度应该是瓶颈了
以前只是在书上看到过IO对程序性能的影响的描述,但是真正自己实践一下,还是被这种效果吓了一跳,这也算是给了我们一个提示:
对程序中IO相关的模块进行性能优化,往往能获得奇效。
C语言文件读写命令
C语言把磁盘文件看成是字符(或字节)的序列,按照存储信息的形式来说,文件主要是有文本文件和二进制文件。
文本文件由一个个字符组成,每个字节存放一个ASCII码制,代表一个字符。
二进制文件把内存中的数据按其在内存中的存储形式原样放入磁盘空间。
二进制文件以及文本文件都可以看做是“数据流”。
流文件的特点是,处理时不需考虑文件中的数据的性质、类型和存放格式。
访问时只是以字节为单位对数据进行存取,没有记录的概念,而将对数据结构的分析、处理等工作都交给后续程序区处理。
系统会自动为这在使用的每个文件开辟一个缓存区,从内存向磁盘输出数据必须先送到内存中的缓存区,装满缓存后才一起送到磁盘。
一、文件的打开与关闭
文件在进行读写操作之前要先打开,使用完毕要关闭。
所谓打开文件,实际上是建立文件的各种有关信息,并使文件指针指向该文件,以便进行其它操作。
关闭文件则断开指针与文件之间的联系,也就禁止再对该文件进行操作。
fopen函数用来打开一个文件,其调用的一般形式为:
文件指针名=fopen(文件名,使用文件方式);
其中:
“文件指针名”必须是被说明为FILE类型的指针变量;
“文件名”是被打开文件的文件名;
“使用文件方式”是指文件的类型和操作要求。
“文件名”是字符串常量或字符串数组。
使用文件的方式共有12种,下面给出了它们的符号和意义。
“r”
只读打开一个文本文件,只允许读数据
“w”
只写打开或建立一个文本文件,只允许写数据
“a”
追加打开一个文本文件,并在文件末尾写数据
“rb”
只读打开一个二进制文件,只允许读数据
“wb”
只写打开或建立一个二进制文件,只允许写数据
“ab”
追加打开一个二进制文件,并在文件末尾写数据
“r+”
读写打开一个文本文件,允许读和写
“w+”
读写打开或建立一个文本文件,允许读写
“a+”
读写打开一个文本文件,允许读,或在文件末追加数据
“rb+”
读写打开一个二进制文件,允许读和写
“wb+”
读写打开或建立一个二进制文件,允许读和写
“ab+”
读写打开一个二进制文件,允许读,或在文件末追加数据
对于文件使用方式有以下几点说明:
1)文件使用方式由r,w,a,t,b,+六个字符拼成,各字符的含义是:
r(read):
读
w(write):
写
a(append):
追加
t(text):
文本文件,可省略不写
b(banary):
二进制文件
+:
读和写
2)凡用“r”打开一个文件时,该文件必须已经存在,且只能从该文件读出。
3)用“w”打开的文件只能向该文件写入。
若打开的文件不存在,则以指定的文件名建立该文件,若打开的文件已经存在,则将该文件删去,重建一个新文件。
4)若要向一个已存在的文件追加新的信息,只能用“a”方式打开文件。
但此时该文件必须是存在的,否则将会出错。
5)在打开一个文件时,如果出错,fopen将返回一个空指针值NULL。
在程序中可以用这一信息来判别是否完成打开文件的工作,并作相应的处理。
二、文件的读写
对文件的读和写是最常用的文件操作。
在C语言中提供了多种文件读写的函数:
·
字符读写函数:
fgetc和fputc
字符串读写函数:
fgets和fputs
数据块读写函数:
freed和fwrite
格式化读写函数:
fscanf和fprinf
下面分别予以介绍。
使用以上函数都要求包含头文件stdio.h。
(1)字符读写函数:
fgetc函数的功能是从指定的文件中读一个字符,函数调用的形式为:
字符变量=fgetc(文件指针);
对于fgetc函数的使用有以下几点说明:
1)在fgetc函数调用中,读取的文件必须是以读或读写方式打开的。
2)读取字符的结果也可以不向字符变量赋值,例如:
fgetc(fp);
但是读出的字符不能保存。
3)在文件内部有一个位置指针。
用来指向文件的当前读写字节。
在文件打开时,该指针总是指向文件的第一个字节。
使用fgetc函数后,该位置指针将向后移动一个字节。
因此可连续多次使用fgetc函数,读取多个字符。
应注意文件指针和文件内部的位置指针不是一回事。
文件指针是指向整个文件的,须在程序中定义说明,只要不重新赋值,文件指针的值是不变的。
文件内部的位置指针用以指示文件内部的当前读写位置,每读写一次,该指针均向后移动,它不需在程序中定义说明,而是由系统自动设置的。
fputc函数的功能为向指定的文件中写入一个字符,函数调用的形式为:
fputc(字符量,文件指量或变量),
例如:
fputc('
a'
其意putc函数的使用也要说明几点:
1)被写入的文件可以用写、读写、追加方式打开,用写或读写方式写入字符从文件首开始。
如需保留原有文件内容,希望写入的字符被写入的文件若不存在,则创建该文件。
2)每写入一个字符,文件内部位置指针向后移动一个字节。
3)fputc函数有一个返回值,如写入成功则返回写入的字符,否则返回一个EOF。
可用此来判断写符,写入一个文件,再把该文件内容读出显示在屏幕上。
【示例程序】
#defineMAXLEN1024
main()
FILE*fpr=fopen("
FILE*fpw=fopen("
2.txt"
a+"
char*arrayCh=NULL;
if(NULL==fpr){
1.txtopenfailed!
exit
(1);
if(NULL==fpw){
2.txtopenfailed!
Bothfileopensuccessd!
while((ch=fgetc(fpr))!
=EOF){