C語言文件的讀寫
我們注重客戶提出的每個(gè)要求,我們充分考慮每一個(gè)細(xì)節(jié),我們積極的做好成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站服務(wù),我們努力開拓更好的視野,通過不懈的努力,創(chuàng)新互聯(lián)贏得了業(yè)內(nèi)的良好聲譽(yù),這一切,也不斷的激勵(lì)著我們更好的服務(wù)客戶。 主要業(yè)務(wù):網(wǎng)站建設(shè),網(wǎng)站制作,網(wǎng)站設(shè)計(jì),重慶小程序開發(fā),網(wǎng)站開發(fā),技術(shù)開發(fā)實(shí)力,DIV+CSS,PHP及ASP,ASP.Net,SQL數(shù)據(jù)庫的技術(shù)開發(fā)工程師。
1. 讀寫字符
C提供fgetc和fputc函數(shù)對文本文件進(jìn)行字符的讀寫,其函數(shù)的原型存于stdio.h頭文件中,格式為:
int fgetc(FILE *stream)
fgetc( )函數(shù)從輸入流的當(dāng)前位置返回一個(gè)字符,并將文件指針指示器移到下一個(gè)字符處,如果已到文件尾,函數(shù)返回EOF,此時(shí)表示本次操作結(jié)束,若讀寫文件完成,則應(yīng)關(guān)閉文件。
int fputc(int ch,FILE *stream)
fputc()函數(shù)完成將字符c h的值寫入所指定的流文件的當(dāng)前位置處,并將文件指針后移一位。fputc()函數(shù)的返回值是所寫入字符的值,出錯(cuò)時(shí)返回EOF。
[例8-2] 將存放于磁盤的指定文本文件按讀寫字符方式逐個(gè)地從文件讀出,然后再將其顯示到屏幕上。采用帶參數(shù)的main( ),指定的磁盤文件名由命令行方式通過鍵盤給定。
#i ncludestdio.h
main(argc,argv)
int argc;
char *argv[];
{
char ch;
FILE *fp;
int i;
if((fp=fopen(argv[1],"r"))==NULL) /* 打開一個(gè)由argv[1]所指的文件*/
{
printf("not open");
exit(0);
}
while ((ch=fgetc(fp))!=EOF) /* 從文件讀一字符,顯示到屏幕*/
putchar(ch);
fclose(fp);
}
程序是一帶參數(shù)的main( )函數(shù),要求以命令行方式運(yùn)行,其參數(shù)argc是用于記錄輸入?yún)?shù)的個(gè)數(shù), argv是指針數(shù)組,用于存放輸入?yún)?shù)的字符串,串的個(gè)數(shù)由argc描述。假設(shè)我們指定讀取的文件名為L8-2.c,并且列表文件內(nèi)容就是源程序。經(jīng)過編 譯和連接生成可執(zhí)行的文件L8-2.exe。運(yùn)行程序l8-2.exe,輸入的命令行方式為:
c:\tcl8-2 L8-2.c
上述程序以命令行方式運(yùn)行,其輸入?yún)?shù)字符串有兩個(gè),即argv[0]="c:\tcl8-2"、argv[1]=" L8-2.c ",argc = 2。故打開的文件是L8-2.c 。程序中對fgetc( )函數(shù)的返回值不斷進(jìn)行測試,若讀到文件尾部或讀文件出錯(cuò),都將返回C的整型常量EOF,其值為非零有效整數(shù)。程序的運(yùn)行輸出為源程序本身:
c:\tcl8-2 L8-2.c
#i nclude stdio.h
main( argc,argv)
int argc;
char *argv[];
{
char ch;
FILE *fp;
int i;
if((fp=fopen(argv[1],"r"))==NULL) /* 打開一個(gè)由argv[1] 所指的文件*/
{
printf("not open");
exit(0);
}
while ((ch=fgetc(fp))!=EOF) /* 從文件讀一字符,顯示到屏幕*/
putchar(ch);
fclose(fp);
}
[例8-3] 從鍵盤輸入字符,存到磁盤文件test.txt中:
#i nclude stdio.h
main( )
{
FILE fp; / *定義文件變量指針* /
char ch;
if((fp=fopen("test.txt","w"))==NULL) /*以只寫方式打開文件*/
{
printf("cannot open file!\n");
exit(0);
}
while ((ch=fgetchar())!='\n') /*只要輸入字符非回車符* /
fputc(ch,fp) /*寫入文件一個(gè)字符*/
fclose(fp);
}
程序通過從鍵盤輸入一以回車結(jié)束的字符串,寫入指定的流文件test.txt,文件以文本只寫方式打開,所以流文件具有可讀性,能支持各種字符處理工具訪問。簡單地說,我們可以通過DOS提供的type命令來列表顯示文件內(nèi)容。
運(yùn)行程序:
I love china!
在DOS操作系統(tǒng)環(huán)境下,利用type 命令顯示test.txt文件如下:
c:\tc type test.txt
I love china!
2. 讀寫字符串
C提供讀寫字符串的函數(shù)原型在stdio.h頭文件中,其函數(shù)形式為:
Char *fgets(char *str,int num,FILE *stream)
fgets() 函數(shù)從流文件stream中讀取至多num-1個(gè)字符,并把它們放入str指向的字符數(shù)組中。讀取字符直到遇見回車符或E O F(文件結(jié)束符)為止,或讀入了所限定的字符數(shù)。
int fputs(char *str,FILE *stream)
fputs( )函數(shù)將str指向的字符串寫入流文件。操作成功時(shí),函數(shù)返回0值,失敗返回非零值。
[例8-4] 向磁盤寫入字符串,并寫入文本文件test.txt:
#i ncludestdio.h
#i ncludestring.h
main( )
{
FILE *fp;
char str[128];
if ((fp=fopen("test.txt","w"))==NULL) /*打開只寫的文本文件*/
{
printf("cannot open file!");
exit(0);
}
while((strlen(gets(str)))!=0)
{ /*若串長度為零,則結(jié)束*/
fputs(str,fp); /*寫入串*/
fputs("\n",fp); /*寫入回車符*/
}
fclose(fp); /*關(guān)文件*/
}
運(yùn)行該程序,從鍵盤輸入長度不超過1 2 7個(gè)字符的字符串,寫入文件。如串長為0,即空串,程序結(jié)束。
輸入:Hello!
How do you do
Good-bye!
運(yùn)行結(jié)束后,我們利用dos的type命令列表文件:
c:\tctype test.txt
Hello!
How do you do
Good-bye!
這里所輸入的空串,實(shí)際為一單獨(dú)的回車符,其原因是gets函數(shù)判斷串的結(jié)束是以回車作標(biāo)志的。
[例8-5] 從一個(gè)文本文件test1.txt中讀出字符串,再寫入令一個(gè)文件test2.txt。
#i ncludestdio.h
#i ncludestring.h
main( )
{
FILE *fp1,*fp2;
char str[128];
if ((fp1=fopen("test1.txt","r"))==NULL)
{ / * 以只讀方式打開文件1 */
printf("cannot open file\n");
exit(0);
}
if((fp2=fopen("test2.txt","w"))==NULL)
{ /*以只寫方式打開文件2 */
printf("cannot open file\n");
exit(0);
}
while ((strlen(fgets(str,128,fp1)))0)
/*從文件中讀回的字符串長度大于0 */
{
fputs(str,fp2 ); /* 從文件1讀字符串并寫入文件2 */
printf("%s",str); /*在屏幕顯示*/
}
fclose(fp1);
fclose(fp2);
}
程序共操作兩個(gè)文件,需定義兩個(gè)文件變量指針,因此在操作文件以前,應(yīng)將兩個(gè)文件以需要的工作方式同時(shí)打開(不分先后),讀寫完成后,再關(guān)閉文件。設(shè)計(jì)過 程是按寫入文件的同時(shí)顯示在屏幕上,故程序運(yùn)行結(jié)束后,應(yīng)看到增加了與原文件相同的文本文件并顯示文件內(nèi)容在屏幕上。
3. 格式化的讀寫
前面的程序設(shè)計(jì)中,我們介紹過利用scanf( )和printf( )函數(shù)從鍵盤格式化輸入及在顯示器上進(jìn)行格式化輸出。對文件的格式化讀寫就是在上述函數(shù)的前面加一個(gè)字母f成為fscanf( )和fprintf( )。其函數(shù)調(diào)用方式:
int fscanf(FILE *stream,char *format,arg_list)
int fprintf(FILE *stream,char *format,arg_list)
其中,stream為流文件指針,其余兩個(gè)參數(shù)與scanf( )和printf( )用法完全相同。
[例8-6] 將一些格式化的數(shù)據(jù)寫入文本文件,再從該文件中以格式化方法讀出顯示到屏
幕上,其格式化數(shù)據(jù)是兩個(gè)學(xué)生記錄,包括姓名、學(xué)號、兩科成績。
#i ncludestdio.h
main( )
{
FILE *fp;
int i;
struct stu{ /*定義結(jié)構(gòu)體類型*/
char name[15];
char num[6];
float score[2];
}student; /*說明結(jié)構(gòu)體變量*/
if((fp=fopen("test1.txt","w"))==NULL)
{ /*以文本只寫方式打開文件*/
printf("cannot open file");
exit(0);
}
printf("input data:\n");
for( i=0;i2;i++)
{
scanf("%s %s %f %f",student.name,student.num,student.score[0],
student.score[1]); /*從鍵盤輸入*/
fprintf(fp,"%s %s %7.2f %7.2f\n",student.name,student.num,
student.score[0],student.score[1]); /* 寫入文件*/
}
fclose(fp); /*關(guān)閉文件*/
if((fp=fopen("test.txt","r"))==NULL)
{ /*以文本只讀方式重新打開文件*/
printf("cannot open file");
exit(0);
}
printf("output from file:\n");
while (fscanf(fp,"%s %s %f %f\n",student.name,student.num,student.score[0],student.score[1])!=EOF)
/ *從文件讀入* /
printf("%s %s %7.2f %7.2f\n",student.name,student.num,
student.score[0],student.score[1]); /* 顯示到屏幕*/
fclose(fp); /*關(guān)閉文件*/
}
程序設(shè)計(jì)一個(gè)文件變量指針,兩次以不同方式打開同一文件,寫入和讀出格式化數(shù)據(jù),有一點(diǎn)很重要,那就是用什么格式寫入文件,就一定用什么格式從文件讀,否則,讀出的數(shù)據(jù)與格式控制符不一致,就造成數(shù)據(jù)出錯(cuò)。上述程序運(yùn)行如下:
input data:
xiaowan j001 87.5 98.4
xiaoli j002 99.5 89.6
output from file:
xiaowan j001 87.50 98.40
xiaoli j002 99.50 89.60
列表文件的內(nèi)容顯示為:
c:\type test.txt
xiaowan j001 87.50 98.40
xiaoli j002 99.50 89.60
此程序所訪問的文件也可以定為二進(jìn)制文件,若打開文件的方式為:
if ((fp=fopen("test1.txt","wb"))==NULL)
{ / * 以二進(jìn)制只寫方式打開文件* /
printf("cannot open file");
exit(0);
}
其效果完全相同。
4. 成塊讀寫
前面介紹的幾種讀寫文件的方法,對其復(fù)雜的數(shù)據(jù)類型無法以整體形式向文件寫入或從文件讀出。C語言提供成塊的讀寫方式來操作文件,使其數(shù)組或結(jié)構(gòu)體等類型可以進(jìn)行一次性讀寫。成塊讀寫文件函數(shù)的調(diào)用形式為:
int fread(void *buf,int size,int count,FILE *stream)
int fwrite(void *buf,int size,int count,FILE *stream)
fread()函數(shù)從stream 指向的流文件讀取count (字段數(shù))個(gè)字段,每個(gè)字段為size(字段長度)個(gè)字符長,并把它們放到b u f(緩沖區(qū))指向的字符數(shù)組中。
fread()函數(shù)返回實(shí)際已讀取的字段數(shù)。若函數(shù)調(diào)用時(shí)要求讀取的字段數(shù)超過文件存放的字段數(shù),則出錯(cuò)或已到文件尾,實(shí)際在操作時(shí)應(yīng)注意檢測。
fwrite( )函數(shù)從buf(緩沖區(qū))指向的字符數(shù)組中,把count(字段數(shù))個(gè)字段寫到stream所指向的流中,每個(gè)字段為size個(gè)字符長,函數(shù)操作成功時(shí)返回所寫字段數(shù)。
關(guān)于成塊的文件讀寫,在創(chuàng)建文件時(shí)只能以二進(jìn)制文件格式創(chuàng)建。
[例8-7] 向磁盤寫入格式化數(shù)據(jù),再從該文件讀出顯示到屏幕。
#i nclude "stdio.h"
#i nclude "stdlib.h"
main( )
{
FILE *fp1;
int i;
struct stu{ / *定義結(jié)構(gòu)體*/
char name[15];
char num[6];
float score[2];
}student;
if((fp1=fopen("test.txt","wb"))==NULL)
{ /*以二進(jìn)制只寫方式打開文件* /
printf("cannot open file");
exit(0);
}
printf("input data:\n");
for( i=0;i2;i++)
{
scanf("%s %s %f %f",student.name,student.num,student.score[0],student.score[1]); /* 輸入一記錄*/
fwrite(student,sizeof(student),1,fp1); /* 成塊寫入文件*/
}
fclose(fp1);
if((fp1=fopen("test.txt","rb"))==NULL)
{ /*重新以二進(jìn)制只寫打開文件*/
printf("cannot open file");
exit(0);
}
printf("output from file:\n");
for (i=0;i2;i++)
{
fread(student,sizeof(student),1,fp1); /* 從文件成塊讀*/
printf("%s %s %7.2f %7.2f\n",student.name,student.num,student.score[0],student.score[1]); /* 顯示到屏幕*/
}
fclose(fp1);
}
運(yùn)行程序:
input data:
xiaowan j001 87.5 98.4
xiaoli j002 99.5 89.6
output from file:
xiaowan j001 87.50 98.40
xiaoli j002 99.50 89.60
通常,對于輸入數(shù)據(jù)的格式較為復(fù)雜的話,我們可采取將各種格式的數(shù)據(jù)當(dāng)做字符串輸入,然后將字符串轉(zhuǎn)換為所需的格式。C提供函數(shù):
int atoi(char *ptr)
float atof(char *ptr)
long int atol(char *ptr)
它們分別將字符串轉(zhuǎn)換為整型、實(shí)型和長整型。使用時(shí)請將其包含的頭文件math.h或stdlib.h寫在程序的前面。
如果圖片或頁面不能正常顯示請點(diǎn)擊這里
fgetc函數(shù)的功能:從文件指針stream指向的文件中讀取一個(gè)字符,讀取一個(gè)字節(jié)后,光標(biāo)位置后移一個(gè)字節(jié)。
格式:int fgetc(FILE *stream);
說明:這個(gè)函數(shù)的返回值,是返回所讀取的一個(gè)字節(jié)。如果讀到文件末尾或者讀取出錯(cuò)時(shí)返回EOF。
示例:
#include?string.h
#include?stdio.h
#include?conio.h
int?main(void)
{
FILE?*stream;
char?string[?]?=?"This?is?a?test";
int?ch;
/*?open?a?file?for?update?*/
stream?=?fopen("DUMMY.FIL",?"w+");
/*?write?a?string?into?the?file?*/
fwrite(string,?strlen(string),?1,?stream);
/*?seek?to?the?beginning?of?the?file?*/
fseek(stream,?0,?SEEK_SET);
do
{
/*?read?a?char?from?the?file?*/
ch?=?fgetc(stream);
/*?display?the?character?*/
putch(ch);
}?
while?(ch?!=?EOF);
fclose(stream);
return?0;
}
getc()和fgetc()函數(shù)即可以接收鍵盤輸入(f)getc(stdin),也可以讀取文本文件(f)getc(file
*stream),成功,返回讀取的字符,否則返回eof,原型都在頭文件stdio.h中,兩者沒有區(qū)別。
putc()和fputc()是輸出函數(shù),(f)putc(stdin)寫字符到顯示器,也可以寫到文本文件fputc(file
*stream)。成功,putc()返回寫出的字符,而fputc()返回寫出的字符數(shù)(奇怪不?),不成功都返回eof。
fgetc():
定義函數(shù)
int fgetc(FILE * stream);
函數(shù)說明
fgetc()從參數(shù)stream所指的文件中讀取一個(gè)字符。若讀到文件尾而無數(shù)據(jù)時(shí)便返回EOF。
返回值
fgetc()會(huì)返回讀取到的字符,若返回EOF則表示到了文件尾。
getc():
功 能: 從流中取字符
用 法: int getc(FILE *stream);
注意: 此函數(shù)被ISO C聲明為一個(gè)宏,所以在用時(shí)不能將其做為函數(shù)指針傳(有一些編譯器將其以函數(shù)形式也給另說)。它的原型如下 #define getc(_stream) (--(_stream)-_cnt = 0?0xff *(_stream)-_ptr++ : _filbuf(_stream))
補(bǔ)充: 在C語言中,用函數(shù)getc(fgetc)從文件讀取字符。getc、fgetc用法相同。 getc的調(diào)用形式:ch=getc(fp);此處的fp是文件指針;函數(shù)功能是從文件指針指向的文件讀入一個(gè)字符,并把它作為函數(shù)值返回給字符型變量ch。