表頭文件 #include<stdio.h>
定義函數 void clearerr(FILE * stream);
函數說明 clearerr()清除參數stream指定的文件流所使用的錯誤旗標。
返回值
fclose(關閉文件)
相關函數 close,fflush,fopen,setbuf
表頭文件 #include<stdio.h>
定義函數 int fclose(FILE * stream);
函數說明 fclose()用來關閉先前fopen()打開的文件。此動作會讓緩衝區內的數據寫入文件中,並釋放系統所提供的文件資源。
返回值 若關文件動作成功則返回0,有錯誤發生時則返回EOF並把錯誤代碼存到errno。
錯誤代碼 EBADF表示參數stream非已打開的文件。
範例 請參考fopen()。
fdopen(將文件描述詞轉爲文件指針)
相關函數 fopen,open,fclose
表頭文件 #include<stdio.h>
定義函數 FILE * fdopen(int fildes,const char * mode);
函數說明 fdopen()會將參數fildes 的文件描述詞,轉換爲對應的文件指針後返回。參數mode 字符串則代表着文件指針的流形態,此形態必須和原先文件描述詞讀寫模式相同。關於mode 字符串格式請參考fopen()。
返回值 轉換成功時返回指向該流的文件指針。失敗則返回NULL,並把錯誤代碼存在errno中。
範例
#include<stdio.h>
main()
{
FILE * fp =fdopen(0,”w+”);
fprintf(fp,”%s\n”,”hello!”);
fclose(fp);
}
執行 hello!
feof(檢查文件流是否讀到了文件尾)
相關函數 fopen,fgetc,fgets,fread
表頭文件 #include<stdio.h>
定義函數 int feof(FILE * stream);
函數說明 feof()用來偵測是否讀取到了文件尾,尾數stream爲fopen()所返回之文件指針。如果已到文件尾則返回非零值,其他情況返回0。
返回值 返回非零值代表已到達文件尾。
fflush(更新緩衝區)
相關函數 write,fopen,fclose,setbuf
表頭文件 #include<stdio.h>
定義函數 int fflush(FILE* stream);
函數說明 fflush()會強迫將緩衝區內的數據寫回參數stream指定的文件中。如果參數stream爲NULL,fflush()會將所有打開的文件數據更新。
返回值 成功返回0,失敗返回EOF,錯誤代碼存於errno中。
錯誤代碼 EBADF 參數stream 指定的文件未被打開,或打開狀態爲只讀。其它錯誤代碼參考write()。
fgetc(由文件中讀取一個字符)
相關函數 open,fread,fscanf,getc
表頭文件 include<stdio.h>
定義函數 nt fgetc(FILE * stream);
函數說明 fgetc()從參數stream所指的文件中讀取一個字符。若讀到文件尾而無數據時便返回EOF。
返回值 getc()會返回讀取到的字符,若返回EOF則表示到了文件尾。
範例
#include<stdio.h>
main()
{
FILE *fp;
int c;
fp=fopen(“exist”,”r”);
while((c=fgetc(fp))!=EOF)
printf(“%c”,c);
fclose(fp);
}
fgets(由文件中讀取一字符串)
相關函數 open,fread,fscanf,getc
表頭文件 include<stdio.h>
定義函數 har * fgets(char * s,int size,FILE * stream);
函數說明 fgets()用來從參數stream所指的文件內讀入字符並存到參數s所指的內存空間,直到出現換行字符、讀到文件尾或是已讀了size-1個字符爲止,最後會加上NULL作爲字符串結束。
返回值 gets()若成功則返回s指針,返回NULL則表示有錯誤發生。
範例
#include<stdio.h>
main()
{
char s[80];
fputs(fgets(s,80,stdin),stdout);
}
執行 this is a test /*輸入*/
this is a test /*輸出*/
fileno(返回文件流所使用的文件描述詞)
相關函數 open,fopen
表頭文件 #include<stdio.h>
定義函數 int fileno(FILE * stream);
函數說明 fileno()用來取得參數stream指定的文件流所使用的文件描述詞。
返回值 返回文件描述詞。
範例
#include<stdio.h>
main()
{
FILE * fp;
int fd;
fp=fopen(“/etc/passwd”,”r”);
fd=fileno(fp);
printf(“fd=%d\n”,fd);
fclose(fp);
}
執行 fd=3
fopen(打開文件)
相關函數 open,fclose
表頭文件 #include<stdio.h>
定義函數 FILE * fopen(const char * path,const char * mode);
函數說明 參數path字符串包含欲打開的文件路徑及文件名,參數mode字符串則代表着流形態。
mode有下列幾種形態字符串:
r 打開只讀文件,該文件必須存在。
r+ 打開可讀寫的文件,該文件必須存在。
w 打開只寫文件,若文件存在則文件長度清爲0,即該文件內容會消失。若文件不存在則建立該文件。
w+ 打開可讀寫文件,若文件存在則文件長度清爲零,即該文件內容會消失。若文件不存在則建立該文件。
a 以附加的方式打開只寫文件。若文件不存在,則會建立該文件,如果文件存在,寫入的數據會被加到文件尾,即文件原先的內容會被保留。
a+ 以附加方式打開可讀寫的文件。若文件不存在,則會建立該文件,如果文件存在,寫入的數據會被加到文件尾後,即文件原先的內容會被保留。
上述的形態字符串都可以再加一個b字符,如rb、w+b或ab+等組合,加入b 字符用來告訴函數庫打開的文件爲二進制文件,而非純文字文件。不過在POSIX系統,包含Linux都會忽略該字符。由fopen()所建立的新文件會具有S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH(0666)權限,此文件權限也會參考umask值。
返回值 文件順利打開後,指向該流的文件指針就會被返回。若果文件打開失敗則返回NULL,並把錯誤代碼存在errno 中。
附加說明 一般而言,開文件後會作一些文件讀取或寫入的動作,若開文件失敗,接下來的讀寫動作也無法順利進行,所以在fopen()後請作錯誤判斷及處理。
範例
#include<stdio.h>
main()
{
FILE * fp;
fp=fopen(“noexist”,”a+”);
if(fp= =NULL) return;
fclose(fp);
}
fputc(將一指定字符寫入文件流中)
相關函數 fopen,fwrite,fscanf,putc
表頭文件 #include<stdio.h>
定義函數 int fputc(int c,FILE * stream);
函數說明 fputc 會將參數c 轉爲unsigned char 後寫入參數stream 指定的文件中。
返回值 fputc()會返回寫入成功的字符,即參數c。若返回EOF則代表寫入失敗。
範例
#include<stdio.h>
main()
{
FILE * fp;
char a[26]=”abcdefghijklmnopqrstuvwxyz”;
int i;
fp= fopen(“noexist”,”w”);
for(i=0;i<26;i++)
fputc(a,fp);
fclose(fp);
}
fputs(將一指定的字符串寫入文件內)
相關函數 fopen,fwrite,fscanf,fputc,putc
表頭文件 #include<stdio.h>
定義函數 int fputs(const char * s,FILE * stream);
函數說明 fputs()用來將參數s所指的字符串寫入到參數stream所指的文件內。
返回值 若成功則返回寫出的字符個數,返回EOF則表示有錯誤發生。
範例 請參考fgets()。
fread(從文件流讀取數據)
相關函數 fopen,fwrite,fseek,fscanf
表頭文件 #include<stdio.h>
定義函數 size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream);
函數說明 fread()用來從文件流中讀取數據。參數stream爲已打開的文件指針,參數ptr 指向欲存放讀取進來的數據空間,讀取的字符數以參數size*nmemb來決定。Fread()會返回實際讀取到的nmemb數目,如果此值比參數nmemb 來得小,則代表可能讀到了文件尾或有錯誤發生,這時必須用feof()或ferror()來決定發生什麼情況。
返回值 返回實際讀取到的nmemb數目。
附加說明
範例
#include<stdio.h>
#define nmemb 3
struct test
{
char name[20];
int size;
}s[nmemb];
int main(){
FILE * stream;
int i;
stream = fopen(“/tmp/fwrite”,”r”);
fread(s,sizeof(struct test),nmemb,stream);
fclose(stream);
for(i=0;i<nmemb;i++)
printf(“name[%d]=%-20s:size[%d]=%d\n”,i,s.name,i,s.size);
}
執行
name[0]=Linux! size[0]=6
name[1]=FreeBSD! size[1]=8
name[2]=Windows2000 size[2]=11
freopen(打開文件)
相關函數 fopen,fclose
表頭文件 #include<stdio.h>
定義函數 FILE * freopen(const char * pathconst char * mode,FILE * stream);
函數說明 參數path字符串包含欲打開的文件路徑及文件名,參數mode請參考fopen()說明。參數stream爲已打開的文件指針。Freopen()會將原stream所打開的文件流關閉,然後打開參數path的文件。
#include<stdio.h>
main()
{
FILE * fp;
fp=fopen(“/etc/passwd”,”r”);
fp=freopen(“/etc/group”,”r”,fp);
fclose(fp);
}
fseek(移動文件流的讀寫位置)
相關函數 rewind,ftell,fgetpos,fsetpos,lseek
表頭文件 #include<stdio.h>
定義函數 int fseek(FILE * stream,long offset,int whence);
函數說明 fseek()用來移動文件流的讀寫位置。參數stream爲已打開的文件指針,參數offset爲根據參數whence來移動讀寫位置的位移數。
參數 whence爲下列其中一種:
SEEK_SET從距文件開頭offset位移量爲新的讀寫位置。SEEK_CUR 以目前的讀寫位置往後增加offset個位移量。
SEEK_END將讀寫位置指向文件尾後再增加offset個位移量。
當whence值爲SEEK_CUR 或SEEK_END時,參數offset允許負值的出現。
下列是較特別的使用方式:
1) 欲將讀寫位置移動到文件開頭時:fseek(FILE *stream,0,SEEK_SET);
2) 欲將讀寫位置移動到文件尾時:fseek(FILE *stream,0,0SEEK_END);
返回值 當調用成功時則返回0,若有錯誤則返回-1,errno會存放錯誤代碼。
附加說明 fseek()不像lseek()會返回讀寫位置,因此必須使用ftell()來取得目前讀寫的位置。
範例
#include<stdio.h>
main()
{
FILE * stream;
long offset;
fpos_t pos;
stream=fopen(“/etc/passwd”,”r”);
fseek(stream,5,SEEK_SET);
printf(“offset=%d\n”,ftell(stream));
rewind(stream);
fgetpos(stream,&pos);
printf(“offset=%d\n”,pos);
pos=10;
fsetpos(stream,&pos);
printf(“offset = %d\n”,ftell(stream));
fclose(stream);
}
執行 offset = 5
offset =0
offset=10
ftell(取得文件流的讀取位置)
相關函數 fseek,rewind,fgetpos,fsetpos
表頭文件 #include<stdio.h>
定義函數 long ftell(FILE * stream);
函數說明 ftell()用來取得文件流目前的讀寫位置。參數stream爲已打開的文件指針。
返回值 當調用成功時則返回目前的讀寫位置,若有錯誤則返回-1,errno會存放錯誤代碼。
錯誤代碼 EBADF 參數stream無效或可移動讀寫位置的文件流。
範例 參考fseek()。
fwrite(將數據寫至文件流)
相關函數 fopen,fread,fseek,fscanf
表頭文件 #include<stdio.h>
定義函數 size_t fwrite(const void * ptr,size_t size,size_t nmemb,FILE * stream);
函數說明 fwrite()用來將數據寫入文件流中。參數stream爲已打開的文件指針,參數ptr 指向欲寫入的數據地址,總共寫入的字符數以參數size*nmemb來決定。Fwrite()會返回實際寫入的nmemb數目。
返回值 返回實際寫入的nmemb數目。
範例
#include<stdio.h>
#define set_s (x,y) {strcoy(s[x].name,y);s[x].size=strlen(y);}
#define nmemb 3
struct test
{
char name[20];
int size;
}s[nmemb];
main()
{
FILE * stream;
set_s(0,”Linux!”);
set_s(1,”FreeBSD!”);
set_s(2,”Windows2000.”);
stream=fopen(“/tmp/fwrite”,”w”);
fwrite(s,sizeof(struct test),nmemb,stream);
fclose(stream);
}
執行 參考fread()。
getc(由文件中讀取一個字符)
相關函數 read,fopen,fread,fgetc
表頭文件 #include<stdio.h>
定義函數 int getc(FILE * stream);
函數說明 getc()用來從參數stream所指的文件中讀取一個字符。若讀到文件尾而無數據時便返回EOF。雖然getc()與fgetc()作用相同,但getc()爲宏定義,非真正的函數調用。
返回值 getc()會返回讀取到的字符,若返回EOF則表示到了文件尾。
範例 參考fgetc()。
getchar(由標準輸入設備內讀進一字符)
相關函數 fopen,fread,fscanf,getc
表頭文件 #include<stdio.h>
定義函數 int getchar(void);
函數說明 getchar()用來從標準輸入設備中讀取一個字符。然後將該字符從unsigned char轉換成int後返回。
返回值 getchar()會返回讀取到的字符,若返回EOF則表示有錯誤發生。
附加說明 getchar()非真正函數,而是getc(stdin)宏定義。
範例
#include<stdio.h>
main()
{
FILE * fp;
int c,i;
for(i=0li<5;i++)
{
c=getchar();
putchar(c);
}
}
執行 1234 /*輸入*/
1234 /*輸出*/
gets(由標準輸入設備內讀進一字符串)
相關函數 fopen,fread,fscanf,fgets
表頭文件 #include<stdio.h>
定義函數 char * gets(char *s);
函數說明 gets()用來從標準設備讀入字符並存到參數s所指的內存空間,直到出現換行字符或讀到文件尾爲止,最後加上NULL作爲字符串結束。
返回值 gets()若成功則返回s指針,返回NULL則表示有錯誤發生。
附加說明 由於gets()無法知道字符串s的大小,必須遇到換行字符或文件尾纔會結束輸入,因此容易造成緩衝溢出的安全性問題。建議使用fgets()取代。
範例 參考fgets()
mktemp(產生唯一的臨時文件名)
相關函數 tmpfile
表頭文件 #include<stdlib.h>
定義函數 char * mktemp(char * template);
函數說明 mktemp()用來產生唯一的臨時文件名。參數template所指的文件名稱字符串中最後六個字符必須是XXXXXX。產生後的文件名會借字符串指針返回。
返回值 文件順利打開後,指向該流的文件指針就會被返回。如果文件打開失敗則返回NULL,並把錯誤代碼存在errno中。
附加說明 參數template所指的文件名稱字符串必須聲明爲數組,如:
char template[ ]=”template-XXXXXX”;
不可用char * template=”template-XXXXXX”;
範例
#include<stdlib.h>
main()
{
char template[ ]=”template-XXXXXX”;
mktemp(template);
printf(“template=%s\n”,template);
}
putc(將一指定字符寫入文件中)
相關函數 fopen,fwrite,fscanf,fputc
表頭文件 #include<stdio.h>
定義函數 int putc(int c,FILE * stream);
函數說明 putc()會將參數c轉爲unsigned char後寫入參數stream指定的文件中。雖然putc()與fputc()作用相同,但putc()爲宏定義,非真正的函數調用。
返回值 putc()會返回寫入成功的字符,即參數c。若返回EOF則代表寫入失敗。
範例 參考fputc()。
putchar(將指定的字符寫到標準輸出設備)
相關函數 fopen,fwrite,fscanf,fputc
表頭文件 #include<stdio.h>
定義函數 int putchar (int c);
函數說明 putchar()用來將參數c字符寫到標準輸出設備。
返回值 putchar()會返回輸出成功的字符,即參數c。若返回EOF則代表輸出失敗。
附加說明 putchar()非真正函數,而是putc(c,stdout)宏定義。
範例 參考getchar()。
rewind(重設文件流的讀寫位置爲文件開頭)
相關函數 fseek,ftell,fgetpos,fsetpos
表頭文件 #include<stdio.h>
定義函數 void rewind(FILE * stream);
函數說明 rewind()用來把文件流的讀寫位置移至文件開頭。參數stream爲已打開的文件指針。此函數相當於調用fseek(stream,0,SEEK_SET)。
返回值
範例 參考fseek()
setbuf(設置文件流的緩衝區)
相關函數 setbuffer,setlinebuf,setvbuf
表頭文件 #include<stdio.h>
定義函數 void setbuf(FILE * stream,char * buf);
函數說明 在打開文件流後,讀取內容之前,調用setbuf()可以用來設置文件流的緩衝區。參數stream爲指定的文件流,參數buf指向自定的緩衝區起始地址。如果參數buf爲NULL指針,則爲無緩衝IO。Setbuf()相當於調用:setvbuf(stream,buf,buf?_IOFBF:_IONBF,BUFSIZ)
返回值
setbuffer(設置文件流的緩衝區)
相關函數 setlinebuf,setbuf,setvbuf
表頭文件 #include<stdio.h>
定義函數 void setbuffer(FILE * stream,char * buf,size_t size);
函數說明 在打開文件流後,讀取內容之前,調用setbuffer()可用來設置文件流的緩衝區。
參數stream爲指定的文件流,參數buf指向自定的緩衝區起始地址,參數size爲緩衝區大小。
返回值
setlinebuf(設置文件流爲線性緩衝區)
相關函數 setbuffer,setbuf,setvbuf
表頭文件 #include<stdio.h>
定義函數 void setlinebuf(FILE * stream);
函數說明 setlinebuf()用來設置文件流以換行爲依據的無緩衝IO。相當於調用:setvbuf(stream,(char * )NULL,_IOLBF,0);請參考setvbuf()。
返回值
setvbuf(設置文件流的緩衝區)
相關函數 setbuffer,setlinebuf,setbuf
表頭文件 #include<stdio.h>
定義函數 int setvbuf(FILE * stream,char * buf,int mode,size_t size);
函數說明 在打開文件流後,讀取內容之前,調用setvbuf()可以用來設置文件流的緩衝區。參數stream爲指定的文件流,參數buf指向自定的緩衝區起始地址,參數size爲緩衝區大小,參數mode有下列幾種
_IONBF 無緩衝IO
_IOLBF 以換行爲依據的無緩衝IO
_IOFBF 完全無緩衝IO。如果參數buf爲NULL指針,則爲無緩衝IO。
返回值
ungetc(將指定字符寫回文件流中)
相關函數 fputc,getchar,getc
表頭文件 #include<stdio.h>
定義函數 int ungetc(int c,FILE * stream);
函數說明 ungetc()將參數c字符寫回參數stream所指定的文件流。這個寫回的字符會由下一個讀取文件流的函數取得。
返回值 成功則返回c 字符,若有錯誤則返回EOF。
abcdefg
一、標準文件的讀寫
1.文件的打開fopen()
文件的打開操作表示將給用戶指定的文件在內存分配一個FILE結構區,並將該結構的指針返回給用戶程序,以後用戶程序就可用此FILE指針來實現對指定文件的存取操作了。當使用打開函數時,必須給出文件名、文件操作方式(讀、寫或讀寫),如果該文件名不存在,就意味着建立(只對寫文件而言,對讀文件則出錯),並將文件指針指向文件開頭。若已有一個同名文件存在,則刪除該文件,若無同名文件,則建立該文件,並將文件指針指向文件開頭。
fopen(char *filename,char *type);
其中*filename是要打開文件的文件名指針,一般用雙引號括起來的文件名錶示,也可使用雙反斜槓隔開的路徑名。而*type參數表示了對打開文件的操作方式。其可採用的操作方式如下:
方式 含義
"r" 打開,只讀
"w" 打開,文件指針指到頭,只寫
"a" 打開,指向文件尾,在已存在文件中追加
"rb" 打開一個二進制文件,只讀
"wb" 打開一個二進制文件,只寫
"ab" 打開一個二進制文件,進行追加
"r+" 以讀/寫方式打開一個已存在的文件
"w+" 以讀/寫方式建立一個新的文本文件
"a+" 以讀/寫方式打開一個文件文件進行追加
"rb+" 以讀/寫方式打開一個二進制文件
"wb+" 以讀/寫方式建立一個新的二進制文件
"rt+" 讀寫打開一個文本文件,允許讀和寫
“wt+” 讀寫打開或建立一個文本文件,允許讀寫
"ab+" 以讀/寫方式打開一個二進制文件進行追加
當用fopen(0成功的打開一個文件時,該函數將返回一個FILE指針,如果文件打開失敗,將返回一個NULL指針。如想打開test文件,進行寫:
FILE *fp;
if((fp=fopen("test","w"))==NULL)
{
printf("File cannot be opened\n");
exit();
}
else
printf("File opened for writing\n");
……
fclose(fp);
DOS操作系統對同時打開的文件數目是有限制的,缺省值爲5,可以通過修改CONFIG.SYS文件改變這個設置。
2.關閉文件函數fclose()
文件操作完成後,必須要用fclose()函數進行關閉,這是因爲對打開的文件進行寫入時,若文件緩衝區的空間未被寫入的內容填滿,這些內容不會寫到打開的文件中去而丟失。只有對打開的文件進行關閉操作時,停留在文件緩衝區的內容才能寫到該文件中去,從而使文件完整。再者一旦關閉了文件,該文件對應的FILE結構將被釋放,從而使關閉的文件得到保護,因爲這時對該文件的存取操作將不會進行。文件的關閉也意味着釋放了該文件的緩衝區。
int fclose(FILE *stream);
它表示該函數將關閉FILE指針對應的文件,並返回一個整數值。若成功地關閉了文件,則返回一個0值,否則返回一個非0值。常用以下方法進行測試:
if(fclose(fp)!=0)
{
printf("File cannot be closed\n");
exit(1);
}
else
printf("File is now closed\n");
當打開多個文件進行操作,而又要同時關閉時,可採用fcloseall()函數,它將關閉所有在程序中打開的文件。
int fcloseall();
該函數將關閉所有已打開的文件,將各文件緩衝區未裝滿的內容寫到相應的文件中去,接着釋放這些緩衝區,並返回關閉文件的數目。如關閉了4個文件,則當執行:
n=fcloseall();
時,n應爲4。
3.文件的讀寫
(1).讀寫文件中字符的函數(一次只讀寫文件中的一個字符):
int fgetc(FILE *stream);
int fgetchar(void);
int fputc(int ch,FILE *stream);
int fputchar(int ch);
int getc(FILE *stream);
int putc(int ch,FILE *stream);
其中fgetc()函數將把由流指針指向的文件中的一個字符讀出,例如:
ch=fgetc(fp);
將把流指針fp指向的文件中的一個字符讀出,並賦給ch,當執行fgetc()函數時,若當時文件指針指到文件尾,即遇到文件結束標誌EOF(其對應值爲-1),該函數返回一個-1給ch,在程序中常用檢查該函數返回值是否爲-1來判斷是否已讀到文件尾,從而決定是否繼續。
#include "stdio.h"
main()
{
FILE *fp;
ch ch;
if((fp=fopen("myfile.tex","r"))==NULL)
{
printf("file cannot be opened\n");
exit(1);
}
while((ch=fgetc(fp))!=EOF) fputc(ch,stdout);
fclose(fp);
}
該程序以只讀方式打開myfile.txt文件,在執行while循環時,文件指針每循環一次後移一個字符位置。用fgetc()函數將文件指針指定的字符讀到ch變量中,然後用fputc()函數在屏幕上顯示,當讀到文件結束標誌EOF時,變關閉該文件。
上面的程序用到了fputc()函數,該函數將字符變量ch的值寫到流指針指定的文件中去,由於流指針用的是標準輸出(顯示器)的FILE指針stdout,故讀出的字符將在顯示器上顯示。又比如:
fputc(ch,fp);
該函數執行結構,將把ch表示的字符送到流指針fp指向的文件中去。
在TC中,putc()等價於fput(),getc()等價於fgetc()。
putchar(c)相當於fputc(c,stdout);getchar()相當於fgetc(stdin)。
注意,這裏使用char ch,其實是不科學的,因爲最後判斷結束標誌時,是看ch!=EOF,而EOF的值爲-1,這顯然和char是不能比較的。所以,某些使用,我們都定義成int ch。
(2).讀寫文件中字符串的函數
char *fgets(char *string,int n,FILE *stream);
char *gets(char *s);
int fprintf(FILE *stream,char *format,variable-list);
int fputs(char *string,FILE *stream);
int fscanf(FILE *stream,char *format,variable-list);
其中fgets()函數將把由流指針指定的文件中n-1個字符,讀到由指針stream指向的字符數組中去,例如:
fgets(buffer,9,fp);
將把fp指向的文件中的8個字符讀到buffer內存區,buffer可以是定義的字符數組,也可以是動態分配的內存區。
注意,fgets()函數讀到'\n'就停止,而不管是否達到數目要求。同時在讀取字符串的最後加上'\0'。
fgets()函數執行完以後,返回一個指向該串的指針。如果讀到文件尾或出錯,則均返回一個空指針NULL,所以長用feof()函數來測定是否到了文件尾或者是ferror()函數來測試是否出錯,例如下面的程序用fgets()函數讀test.txt文件中的第一行並顯示出來:
#include "stdio.h"
main()
{
FILE *fp;
char str[128];
if((fp=fopen("test.txt","r"))==NULL)
{
printf("cannot open file\n");
exit(1);
}
while(!feof(fp))
{
if(fgets(str,128,fp)!=NULL) printf("%s",str);
}
fclose(fp);
}
gets()函數執行時,只要未遇到換行符或文件結束標誌,將一直讀下去。因此讀到什麼時候爲止,需要用戶進行控制,否則可能造成存儲區的溢出。
fputs()函數想指定文件寫入一個由string指向的字符串,'\0'不寫入文件。
fprintf()和fscanf()同printf()和scanf()函數類似,不同之處就是printf()函數是想顯示器輸出,fprintf()則是向流指針指向的文件輸出;fscanf()是從文件輸入。
下面程序是向文件test.dat裏輸入一些字符:
#include<stdio.h>
main()
{
char *s="That's good news";
int i=617;
FILE *fp;
fp=fopne("test.dat", "w");
fputs("Your score of TOEFLis",fp);
fputc(':', fp);
fprintf(fp, "%d\n", i);
fprintf(fp, "%s", s);
fclose(fp);
}
用DOS的TYPE命令顯示TEST.DAT的內容如下所示:
屏幕顯示
Your score of TOEFL is: 617
That's good news
下面的程序是把上面的文件test.dat裏的內容在屏幕上顯示出來:
#include<stdio.h>
main()
{
char *s, m[20];
int i;
FILE *fp;
fp=fopen("test.dat", "r");
fgets(s, 24, fp);
printf("%s", s);
fscanf(fp, "%d", &i);
printf("%d", i);
putchar(fgetc(fp));
fgets(m, 17, fp);
puts(m);
fclose(fp);
getch();
}
運行後屏幕顯示:
Your score of TOEFL is: 617
That's good news
4.清除和設置文件緩衝區
(1).清除文件緩衝區函數:
int fflush(FILE *stream);
int flushall();
fflush()函數將清除由stream指向的文件緩衝區裏的內容,常用於寫完一些數據後,立即用該函數清除緩衝區,以免誤操作時,破壞原來的數據。
flushall()將清除所有打開文件所對應的文件緩衝區。
(2).設置文件緩衝區函數
void setbuf(FILE *stream,char *buf);
void setvbuf(FILE *stream,char *buf,int type,unsigned size);
這兩個函數將使得打開文件後,用戶可建立自己的文件緩衝區,而不使用fopen()函數打開文件設定的默認緩衝區。
對於setbuf()函數,buf指出的緩衝區長度由頭文件stdio.h中定義的宏BUFSIZE的值決定,缺省值爲512字節。當選定buf爲空時,setbuf函數將使的文件I/O不帶緩衝。而對setvbuf函數,則由malloc函數來分配緩衝區。參數size指明瞭緩衝區的長度(必須大於0),而參數type則表示了緩衝的類型,其值可以取如下值:
type 值 含義
_IOFBF 文件全部緩衝,即緩衝區裝滿後,才能對文件讀寫
_IOLBF 文件行緩衝,即緩衝區接收到一個換行符時,才能對文件讀寫
_IONBF 文件不緩衝,此時忽略buf,size的值,直接讀寫文件,不再經過文件緩衝區緩衝
5.文件的隨機讀寫函數
前面介紹的文件的字符/字符串讀寫,均是進行文件的順序讀寫,即總是從文件的開頭開始進行讀寫。這顯然不能滿足我們的要求,C語言提供了移動文件指針和隨機讀寫的函數,它們是:
(1).移動文件指針函數:
long ftell(FILE *stream);
int rewind(FILE *stream);
fseek(FILE *stream,long offset,int origin);
函數ftell()用來得到文件指針離文件開頭的偏移量。當返回值是-1時表示出錯。
rewind()函數用於文件指針移到文件的開頭,當移動成功時,返回0,否則返回一個非0值。
fseek()函數用於把文件指針以origin爲起點移動offset個字節,其中origin指出的位置可有以下幾種:
origin 數值 代表的具體位置
SEEK_SET 0 文件開頭
SEEK_CUR 1 文件指針當前位置
SEEK_END 2 文件尾
例如:
fseek(fp,10L,0);
把文件指針從文件開頭移到第10字節處,由於offset參數要求是長整型數,故其數後帶L。
fseek(fp,-15L,2);
把文件指針從文件尾向前移動15字節。
(2).文件隨機讀寫函數
int fread(void *ptr,int size,int nitems,FILE *stream);
int fwrite(void *ptr,int size,int nitems,FILE *stream);
fread()函數從流指針指定的文件中讀取nitems個數據項,每個數據項的長度爲size個字節,讀取的nitems數據項存入由ptr指針指向的內存緩衝區中,
在執行fread()函數時,文件指針隨着讀取的字節數而向後移動,最後移動結束的位置等於實際讀出的字節數。該函數執行結束後,將返回實際讀出的數據項數,
這個數據項數不一定等於設置的nitems,因爲若文件中沒有足夠的數據項,或讀中間出錯,都會導致返回的數據項數少於設置的nitems。當返回數不等於nitems時
,可以用feof()或ferror()函數進行檢查。
fwrite()函數從ptr指向的緩衝區中取出長度爲size字節的nitems個數據項,寫入到流指針stream指向的文件中,執行該操作後,文件指針將向後移動,
移動的字節數等於寫入文件的字節數目。該函數操作完成後,也將返回寫入的數據項數。
二、非標準文件的讀寫
這類函數最早用於UNIX操作系統,ANSI標準未定義,但有時也經常用到,DOS 3.0以上版本支持這些函數。它們的頭文件爲io.h。
由於我們不常用這些函數,所以在這裏就簡單說一下。
1.文件的打開和關閉
open()函數的作用是打開文件,其調用格式爲:
int open(char *filename, int access);
該函數表示按access的要求打開名爲filename的文件,返回值爲文件描述字,其中access有兩部分內容:
基本模式和修飾符, 兩者用" "("或")方式連接。修飾符可以有多個, 但基本模式只能有一個。
access的規定
--------------------------------------------------------
基本模式 含義 修飾符 含 義
--------------------------------------------------------
O_RDONLY 只讀 O_APPEND 文件指針指向末尾
O_WRONLY 只寫 O_CREAT 文件不存在時創建文件, 屬性按基本模式屬性
O_RDWR 讀寫 O_TRUNC 若文件存在, 將其長度縮爲0, 屬性不變
O_BINARY 打開一個二進制文件
O_TEXT 打開一個文字文件
---------------------------------------------------------
open()函數打開成功, 返回值就是文件描述字的值(非負值), 否則返回-1。
close()函數的作用是關閉由open()函數打開的文件, 其調用格式爲:
int close(int handle);
該函數關閉文件描述字handle相連的文件。
2.讀寫函數
int read(int handle, void *buf, int count);
read()函數從handle(文件描述字)相連的文件中, 讀取count個字節放到buf所指的緩衝區中,
返回值爲實際所讀字節數, 返回-1表示出錯。返回0 表示文件結束。
write()函數的調用格式爲:
int write(int handle, void *buf, int count);
write()函數把count個字節從buf指向的緩衝區寫入與handle相連的文件中, 返回值爲實際寫入的字節數。
3.隨機定位函數
lseek()函數的調用格式爲:
int lseek(int handle, long offset, int fromwhere);
該函數對與handle相連的文件位置指針進行定位,功能和用法與fseek()函數相同。
tell()函數的調用格式爲:
long tell(int handle);
該函數返回與handle相連的文件現生位置指針, 功能和用法與ftell()相同