文件是一種信息存儲的方式,程序設(shè)計不可避免要進行各種文件操作,一個程序在運行過程中通常要從文件中讀取信息,在文件中存儲計算結(jié)果。
1 C文件的概念
在C語言中實現(xiàn)文件操作一般采取兩種途徑。
第一種:調(diào)用C語言中有關(guān)文件處理的標(biāo)準(zhǔn)庫函數(shù)。
第二種:直接調(diào)用操作系統(tǒng)提供的有關(guān)方面的功能。
所謂"文件"一般指存儲在外部介質(zhì)上數(shù)據(jù)的集合。
2 文件類型指針
Turbo C在stdio.h文件中有以下的文件類型聲明:
typedef struct
{ short level; /*緩沖區(qū)"滿"或"空"的程度*/
unsigned flags; /*文件狀態(tài)標(biāo)志*/
char fd; /*文件描述符*/
unsigned char hold; /*如無緩沖區(qū)不讀取字符*/
short bsize; /*級沖區(qū)的大小*/
unsigned char *baffer; /*數(shù)據(jù)緩沖區(qū)的位置*/
unsigned ar *curp; /*指針,當(dāng)前的指向*/
unsigned istemp; /*臨時文件,指示器*/
short token; /*用于有效性檢查*/
}FILE;
3 文件的打開和關(guān)閉
和其他高級語言一樣,對文件讀寫之前應(yīng)該"打開"該文件,在使用結(jié)束之后應(yīng)關(guān)閉該文件。
一、文件的打開(fopen函數(shù))
ANSI C規(guī)定了標(biāo)準(zhǔn)輸入輸出函數(shù)庫,用fopen()函數(shù)來實現(xiàn)打開文件。fopen函數(shù)的調(diào)用方式通常為:
FILE *fp;
fp=fopen(文件名,使用文件方式);
例如:fp=fopen("al",nr");
它表示要打開名字為al的文件,使用文件方式為"讀入"(r代表read,即讀入),fopen函數(shù)帶回指向al文件的指針并賦給fp,這樣fp就和文件al相聯(lián)系了,或者說,fp指向al文件。可以看出,在打開一個文件時,通知給編譯系統(tǒng)以下3個信息:①需要打開的文件名,也就是準(zhǔn)備訪問的文件的名字。②使用文件的方式("讀"還是"寫"等)。③讓哪一個指針變量指向被打開的文件。
說明:
(1)用"r"方式打開的文件只能用于向計算機輸人而不能用作向該文件輸出數(shù)據(jù),而且該文件應(yīng)該已經(jīng)存在,不能用"r"方式打開一個并不存在的文件(即輸入文件),否則出錯。
(2)用"w"方式打開的文件只能用于向該文件寫數(shù)據(jù)(即輸出文件),而不能用來向計算機輸入。如果原來不存在該文件,則在打開時新建立一個以指定的名字命名的文件。如果原來已存在一個以該文件名命名的文件,則在打開時將該文件刪去,然后重新建立一個新文件。
(3)如果希望向文件末尾添加新的數(shù)據(jù)(不希望刪除原有數(shù)據(jù)),則應(yīng)該用"a"方式打開。但此時該文件必須已存在,否則將得到出錯信息。打開時,位置指針移到文件末尾。
(4)用"r+"、"w+"、"a+"方式打開的文件既可以用來輸人數(shù)據(jù),也可以用來輸出數(shù)據(jù)。用"r+"方式時該文件應(yīng)該已經(jīng)存在,以便能向計算機輸入數(shù)據(jù)。用"w+"方式則新建立一個文件,先向此文件寫數(shù)據(jù),然后可以讀此文件中的數(shù)據(jù)。用"a+"方式打開的文件,原來的文件不被刪去,位置指針移到文件末尾,可以添加,也可以讀。
(5)如果不能實現(xiàn)"打開"的任務(wù),fopen函數(shù)將會帶回一個出錯信息。出錯的原因可能是用"r"方式打開一個并不存在的文件;磁盤出故障;磁盤己滿無法建立新文件等。此時fopen函數(shù)將帶回一個空指針值NULL(NULL在stdio.h文件中已被定義為0)。
(6)用以上方式可以打開文本文件或二進制文件,這是ANSI C的規(guī)定,用同一種緩沖文件系統(tǒng)來處理文本文件和二進制文件。但目前使用的有些C編譯系統(tǒng)可能不完全提供所有這些功能(例如有的只能用"r"、"w"、"a"方式),有的C版本不用"r+"、"w+"、"a+",而用"rw"、"wr"、"ar"等,請讀者注意所用系統(tǒng)的規(guī)定。
(7)在向計算機輸人文本文件時,將回車換行符轉(zhuǎn)換為一個換行符,在輸出時把換行符轉(zhuǎn)換成為回車和換行兩個字符。在用二進制文件時,不進行這種轉(zhuǎn)換,在內(nèi)存中的數(shù)據(jù)形式與輸出到外部文件中的數(shù)據(jù)形式完全一致,一一對應(yīng)。
(8)在程序開始運行時,系統(tǒng)自動打開3個標(biāo)準(zhǔn)文件:標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)出錯輸出。
二、文件的關(guān)閉(fclose 函數(shù))
fclose(文件指針);
例如:fclose(fp);
4 文件的讀寫
一、fputc函數(shù)和fgetc函數(shù)(putc函數(shù)和getc函數(shù))
1. fputc函數(shù)
把一個字符寫到磁盤文件上去。其一般調(diào)用形式為:
fputc(ch,fp);
2. fgetc函數(shù)
從指定的文件讀入一個字符,該文件必須是以讀或讀寫方式打開的。fgetc函數(shù)的調(diào)用形式為:
ch=fgetc(fp);
如果想從一個磁盤文件順序讀入字符并在屏幕上顯示出來,可以:
ch=fgetc(fp);
while(ch!=EOF)
{ putchar(ch);
ch=fgetc(fp);
}
如果想順序讀入一個二進制文件中的數(shù)據(jù),可以用:
while(! feof(fp))
{c=fgetc(fp);
}
3. fputc和fgetc函數(shù)使用舉例
例11.1 從鍵盤輸入一些字符,逐個把它們送到磁盤上去,直到輸入一個"#"為止。
#include <stdio.h>
main()
{ file*fp;
char ch,filename[l0];
scanf("%s",filename);
if((fp=fopen(filename,"w"))==NULL)
{printf("cannot open file\n");
exit(0);
ch=getchar();
while(ch!='#')
{
fputc(ch,fp);putchar(ch);
ch=getchar();
}
fclose(fp);
}
運行情況如下:
file1.c (輸入磁盤文件名)
computer and c# (輸入一個字符串)
computer and c (輸出一個字符串)
可以用DOS命令將file1.c文件中的內(nèi)容打印出來;
C>type file.c
computer and c
證明了在file1.c 文件中已存入了"computer and c"的信息。
二、fread函數(shù)和fwrite函數(shù)
ANSI C標(biāo)準(zhǔn)提出設(shè)置兩個函數(shù)(fread和fwrite),用來讀寫一個數(shù)據(jù)塊。它們的一般調(diào)用形式為:
fread(buffer,size,count,fp);
fwrite(buffer,size,count,fp);
其中:
buffer:是一個指針。對fread來說,它是讀入數(shù)據(jù)的存放地址。對fwrite比來說,是要輸出數(shù)據(jù)的地址(以上指的是起始地址)。
size:要讀寫的字節(jié)數(shù)。
count:要進行讀寫多少個size字節(jié)的數(shù)據(jù)項。
fp:文件型指針。
如果文件以二進制形式打開,用fread和fwrite函數(shù)就可以讀寫任何類型的信息,如:
fread(f,4,2,fp);
其中f是一個實型數(shù)組名。一個實型變量占4個字節(jié)。這個函數(shù)從fp所指向的文件讀入2次(每次4個字節(jié))數(shù)據(jù),存儲到數(shù)組f中。
如果有一個如下的結(jié)構(gòu)體類型:
struct student_type
{char name[10];
int num;
int age;
char addr[30];
}stud[40];
結(jié)構(gòu)體數(shù)組stud有40個元素,每一個元素用來存放一個學(xué)生的數(shù)據(jù)(包括姓名、學(xué)號、年齡、地址)。假設(shè)學(xué)生的數(shù)據(jù)已存放在磁盤文件中,可以用下面的for語句和fread函數(shù)讀入40個學(xué)生的數(shù)據(jù):
for(i=0;i<40;i++)
fread(&stud[i],sizeof(struct student_type),l,fp);
同樣,以下for語句和fwrite函數(shù)可以將內(nèi)存中的學(xué)生數(shù)據(jù)輸出到磁盤文件中去:
for(i=0;i<40,i++)
fwrite(&stud[i],sizeof(struct student_type),l,fp);
如果fread或fwrite調(diào)用成功,則函數(shù)返回值為count的值,即輸人或輸出數(shù)據(jù)項的完整個數(shù)。
11.4.3 fprintf函數(shù)和fscanf函數(shù)
它們的一般調(diào)用方式為:
fprintf(文件指針,格式字符串,輸出表列);
fscanf(文件指針,格式字符串,輸入表列);
例如:
fprintf(fp,"%d,%6.2f",i,t);
它的作用是將整型變量i和實型變量t的值按%d和%6.2f的格式輸出到fp指向的文件上。