當檔案按指定的工作方式開啟以後,就可以執行對檔案的讀和寫。下面按檔案的性質分類進行操作。針對文字檔和二進位檔案的不同性質,對文字檔來說,可按字元讀寫或按字串讀寫;對二進位檔案來說,可進行成塊的讀寫或格式化的讀寫。
1. 讀寫字元
C提供fgetc和fputc函數對文字檔進行字元的讀寫,其函數的原型存於stdio.h標頭檔中,格式為:
int fgetc(FILE *stream)
fgetc( )函數從輸入資料流的當前位置返回一個字元,並將檔案指標指標移到下一個字元處,如果已到檔案尾,函數返回EOF,此時表示本次操作結束,若讀寫檔案完成,則應關閉檔案。
int fputc(int ch,FILE *stream)
fputc()函數完成將字元c h的值寫入所指定的流檔案的當前位置處,並將檔案指標後移一位。fputc()函數的傳回值是所寫入字元的值,出錯時返回EOF。
[例8-2] 將存放於磁碟的指定文字檔按讀寫字元方式逐個地從檔案讀出,然後再將其顯示到螢幕上。採用帶參數的main( ),指定的磁碟檔案名稱由命令列方式通過鍵盤給定。
#i nclude<stdio.h>
main(argc,argv)
int argc;
char *argv[];
{
char ch;
FILE *fp;
int i;
if((fp=fopen(argv[1],"r"))==NULL) /* 開啟一個由argv[1]所指的檔案*/
{
printf("not open");
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-2 L8-2.c
上述程式以命令列方式運行,其輸入參數字串有兩個,即argv[0]="c:/tc>l8-2"、argv[1]=" L8-2.c ",argc = 2。故開啟的檔案是L8-2.c 。程式中對fgetc( )函數的傳回值不斷進行測試,若讀到檔案尾部或讀檔案出錯,都將返回C的整型常量EOF,其值為非零有效整數。程式的運行輸出為來源程式本身:
c:/tc>l8-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) /* 開啟一個由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) /*寫入檔案一個字元*/
fclose(fp);
}
程式通過從鍵盤輸入一以斷行符號結束的字串,寫入指定的流檔案test.txt,檔案以文本唯寫方式開啟,所以流檔案具有可讀性,能支援各種字元處理工具訪問。簡單地說,我們可以通過DOS提供的type命令來列表顯示檔案內容。
運行程式:
I love china!
在DOS作業系統環境下,利用type 命令顯示test.txt檔案如下:
c:/tc> type test.txt
I love china!
2. 讀寫字串
C提供讀寫字串的函數原型在stdio.h標頭檔中,其函數形式為:
Char *fgets(char *str,int num,FILE *stream)
fgets() 函數從流檔案stream中讀取至多num-1個字元,並把它們放入str指向的字元數組中。讀取字元直到遇見斷行符號符或E O F(檔案結束符)為止,或讀入了所限定的字元數。
int fputs(char *str,FILE *stream)
fputs( )函數將str指向的字串寫入流檔案。操作成功時,函數返回0值,失敗返回非零值。
[例8-4] 向磁碟寫入字串,並寫入文字檔test.txt:
#i nclude<stdio.h>
#i nclude<string.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)
{ /*若串長度為零,則結束*/
fputs(str,fp); /*寫入串*/
fputs("/n",fp); /*寫入斷行符號符*/
}
fclose(fp); /*關檔案*/
}
運行該程式,從鍵盤輸入長度不超過1 2 7個字元的字串,寫入檔案。如串長為0,即空串,程式結束。
輸入:Hello!
How do you do
Good-bye!
運行結束後,我們利用dos的type命令列表檔案:
c:/tc>type test.txt
Hello!
How do you do
Good-bye!
這裡所輸入的空串,實際為一單獨的斷行符號符,其原因是gets函數判斷串的結束是以斷行符號作標誌的。
[例8-5] 從一個文字檔test1.txt中讀出字串,再寫入令一個檔案test2.txt。
#i nclude<stdio.h>
#i nclude<string.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);
}
程式共操作兩個檔案,需定義兩個檔案變數指標,因此在操作檔案以前,應將兩個檔案以需要的工作方式同時開啟(不分先後),讀寫完成後,再關閉檔案。設計過 程是按寫入檔案的同時顯示在螢幕上,故程式運行結束後,應看到增加了與原檔案相同的文字檔並顯示檔案內容在螢幕上。
3. 格式化的讀寫
前面的程式設計中,我們介紹過利用scanf( )和printf( )函數從鍵盤格式化輸入及在顯示器上進行格式化輸出。對檔案的格式化讀寫就是在上述函數的前面加一個字母f成為fscanf( )和fprintf( )。其函數調用方式:
int fscanf(FILE *stream,char *format,arg_list)
int fprintf(FILE *stream,char *format,arg_list)
其中,stream為流檔案指標,其餘兩個參數與scanf( )和printf( )用法完全相同。
[例8-6] 將一些格式化的資料寫入文字檔,再從該檔案中以格式化方法讀出顯示到屏
幕上,其格式化資料是兩個學生記錄,包括姓名、學號、兩科成績。
#i nclude<stdio.h>
main( )
{
FILE *fp;
int i;
struct stu{ /*定義結構體類型*/
char name[15];
char num[6];
float score[2];
}student; /*說明結構體變數*/
if((fp=fopen("test1.txt","w"))==NULL)
{ /*以文本唯寫方式開啟檔案*/
printf("cannot open file");
exit(0);
}
printf("input data:/n");
for( i=0;i<2;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); /*關閉檔案*/
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); /*關閉檔案*/
}
程式設計一個檔案變數指標,兩次以不同方式開啟同一檔案,寫入和讀出格式化資料,有一點很重要,那就是用什麼格式寫入檔案,就一定用什麼格式從檔案讀,否則,讀出的資料與格式控制符不一致,就造成資料出錯。上述程式運行如下:
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
列表檔案的內容顯示為:
c:/>type test.txt
xiaowan j001 87.50 98.40
xiaoli j002 99.50 89.60
此程式所訪問的檔案也可以定為二進位檔案,若開啟檔案的方式為:
if ((fp=fopen("test1.txt","wb"))==NULL)
{ / * 以二進位唯寫方式開啟檔案* /
printf("cannot open file");
exit(0);
}
其效果完全相同。
4. 成塊讀寫
前面介紹的幾種讀寫檔案的方法,對其複雜的資料類型無法以整體形式向檔案寫入或從檔案讀出。C語言提供成塊的讀寫方式來操作檔案,使其數組或結構體等類型可以進行一次性讀寫。成塊讀寫檔案函數的調用形式為:
int fread(void *buf,int size,int count,FILE *stream)
int fwrite(void *buf,int size,int count,FILE *stream)
fread()函數從stream 指向的流檔案讀取count (欄位數)個欄位,每個欄位為size(欄位長度)個字元長,並把它們放到b u f(緩衝區)指向的字元數組中。
fread()函數返回實際已讀取的欄位數。若函數調用時要求讀取的欄位數超過檔案存放的欄位數,則出錯或已到檔案尾,實際在操作時應注意檢測。
fwrite( )函數從buf(緩衝區)指向的字元數組中,把count(欄位數)個欄位寫到stream所指向的流中,每個欄位為size個字元長,函數操作成功時返回所寫欄位數。
關於成塊的檔案讀寫,在建立檔案時只能以二進位檔案格式建立。
[例8-7] 向磁碟寫入格式化資料,再從該檔案讀出顯示到螢幕。
#i nclude "stdio.h"
#i nclude "stdlib.h"
main( )
{
FILE *fp1;
int i;
struct stu{ / *定義結構體*/
char name[15];
char num[6];
float score[2];
}student;
if((fp1=fopen("test.txt","wb"))==NULL)
{ /*以二進位唯寫方式開啟檔案* /
printf("cannot open file");
exit(0);
}
printf("input data:/n");
for( i=0;i<2;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)
{ /*重新以二進位唯寫開啟檔案*/
printf("cannot open file");
exit(0);
}
printf("output from file:/n");
for (i=0;i<2;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);
}
運行程式:
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
通常,對於輸入資料的格式較為複雜的話,我們可採取將各種格式的資料當做字串輸入,然後將字串轉換為所需的格式。C提供函數:
int atoi(char *ptr)
float atof(char *ptr)
long int atol(char *ptr)
它們分別將字串轉換為整型、實型和長整型。使用時請將其包含的標頭檔math.h或stdlib.h寫在程式的前面。
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/jiji262/archive/2007/10/21/1835971.aspx