所謂“文件”是指一組相關(guān)數(shù)據(jù)的有序集合洛巢,該數(shù)據(jù)的集合的名字就是文件名。文件可以分為很多類次兆,如源程序文件稿茉、目標(biāo)文件、可執(zhí)行文件芥炭、庫文件等等漓库。
文件通常是存放在外部介質(zhì)上的(例如磁盤等),在使用時才會被調(diào)入內(nèi)存中并執(zhí)行园蝠。從用戶的角度來看文件可以分為普通文件和設(shè)備文件米苹。
普通文件是指存放在磁盤或者其它外部介質(zhì)上的一個有序的集合,可以是源文件砰琢、目標(biāo)文件蘸嘶、可執(zhí)行程序等;也可以是一組待輸入處理的原始數(shù)據(jù)陪汽,或是一組輸出的結(jié)果训唱。對于源文件、目標(biāo)文件挚冤、可執(zhí)行程序可以稱作程序文件况增,而輸入輸出數(shù)據(jù)可以稱作數(shù)據(jù)文件。
設(shè)備文件是指與主機相聯(lián)的各種外部設(shè)備训挡,如顯示器澳骤、打印機、鍵盤等澜薄。在操作系統(tǒng)中为肮,把外部設(shè)備也看作是一個文件來進行管理,把他們的輸入輸出等同于對磁盤文件的讀寫肤京。
從文件編碼的形式來看颊艳,文件可以分為ASCII碼文件和二進制碼文件。ASCII碼文件也稱作為文本文件,這種文件在磁盤中存放時每個字符對應(yīng)一個字節(jié)棋枕,用于存放相應(yīng)的ASCII碼白修。
二進制文件是以二進制編碼的方式來編寫文件的。二進制文件雖然可以顯示在屏幕上重斑,但是卻不能讀懂兵睛。
文件的指針
在C語言中用一個指針變量指向一個文件,那么這個指針稱為文件指針窥浪。另外祖很,我們通過文件指針就可以對所指的文件進行各種操作。
一般形式為:
FILE* 文件變量標(biāo)識符
解釋:FILE應(yīng)該是大寫的寒矿,它實際上是由系統(tǒng)定義的一個結(jié)構(gòu)體突琳,該結(jié)構(gòu)體包含了文件名、文件狀態(tài)和文件當(dāng)前位置等信息符相,因此在編寫程序的時候我們不需要過于關(guān)心FILE結(jié)構(gòu)的細節(jié)部分拆融。
// 案例1:
FILE *fp;
/*說明:
fp表示FILE結(jié)構(gòu)的指針變量啊终,通過fp可以找到存放某一個文件信息的結(jié)構(gòu)變量镜豹,
然后按照結(jié)構(gòu)體提供的信息找到該文件,并對文件進行操作蓝牲。*/
文件的打開和關(guān)閉
文件在進行讀寫操作之前趟脂,要打開文件,當(dāng)使用完后應(yīng)關(guān)閉文件例衍。打開文件就是建立文件的各種有關(guān)信息昔期,并使文件指針指向文件,以便進行其他操作佛玄。而關(guān)閉文件就是切斷文件指針和文件之間的關(guān)系硼一,換而言之,就是禁止利用指針操作文件梦抢。
在C語言中般贼,文件操作都是由庫函數(shù)完成的。如fopen 和 fclose奥吩。
1. 文件的打開 fopen()
fopen() 函數(shù)是用來打開一個文件哼蛆,其一般的調(diào)用形式為:
文件指針名 = fopen(文件名,使用文件的方式)霞赫;
注釋:
- 文件指針名:必須被說明為FILE類型的指針變量腮介;
- 文件名:被打開文件的文件名;
- 使用文件的方式:文件的類型和操作要求
// 案例2:
FILE* fp;
fp = fopen("text","r");
/*說明:
在當(dāng)前目錄下打開文件text绩脆,只允許“讀”的操作萤厅,并且讓fp指針指向該文件*/
使用文件的方式有12種橄抹,如下所示:
|使用文件方 | 意義 |
|----------|------------------------------:|
|“rt” | 只讀打開一個文本靴迫,只允許讀|
|“wt” | 只寫打開或者建立一個文件惕味,只允許寫數(shù)據(jù)|
|“at” | 追加打開一個文件,并在文件末尾寫數(shù)據(jù)|
|“rb” | 只讀打開一個二進制文件玉锌,只允許讀|
|“wt” | 只寫打開或者建立一個而進制文件名挥,只允許寫|
|“ab” | 追加打開一個二進制文件,并在文件末尾寫數(shù)據(jù)|
|“rt+” | 讀寫打開一個文件主守,允許讀和寫 |
| “wt+” | 讀寫打開或建立一個文件禀倔,允許讀寫|
|“at+” | 讀寫打開一個文件,允許讀参淫,或在文件末尾追加數(shù)據(jù)|
|“rb+” | 讀寫打開一個二進制文件救湖,允許讀寫|
|“wb+” | 讀寫打開或者建立一個二進制文件,允許讀寫 |
|“ab+” | 讀寫打開一個二進制文件涎才,允許讀鞋既,或在文件末追加數(shù)據(jù)|
說明:
由r、w耍铜、a邑闺、t、b棕兼、+六個字符拼成陡舅,個字符的意義:
- r(read):讀
- w(write):寫
- a(append):追加
- t(text):文本文件,可省略不寫
- b(banary):二進制文件
6.+:讀和寫
// 案例3:
FILE* fp;
fd = fopen("./text","r");
if (NULL == fd)
{
printf("open error\n");
exit(1);
}
// 用讀“r”的方式打開文件“./text”伴挚;若文件打開失敗時靶衍,fp為空,輸出open error茎芋。
2. 文件的關(guān)閉
fclose()函數(shù)是指當(dāng)文件使用完后颅眶,需要關(guān)閉文件。其一般形式為:
fclose(文件指針)败徊;
// 案例4:
fclose(fp);
// 說明:正常關(guān)閉文件時帚呼,fclose()函數(shù)的返回值是0。若返回一個非零的值皱蹦,則表示關(guān)閉文件時發(fā)生錯誤
文件的讀寫
文件的讀寫是有多重方式的煤杀,它可以一個字節(jié)一個字節(jié)的讀或?qū)懀部梢允且淮淮淖x或?qū)懟Σ浮N募淖x寫可以分為下面四類沈自,且它們的頭文件均是<stdio.h>。
1. 字符讀寫函數(shù)fgetc 和 fputc
字符的讀寫函數(shù)是以字節(jié)為單位讀寫函數(shù)辜妓。每一次可以從文件讀出或向文件內(nèi)寫入一個字符枯途。
讀字符函數(shù)fgetc() 的一般形式:
字符變量 = fgetc(文件指針)忌怎;
說明:將文件中的一個字符讀取出來,然后存放在字符變量中酪夷。
寫字符函數(shù)fputs() 的一般形式:
fputs(字符量榴啸,文件指針);
說明:將字符量中的字符晚岭,存放在想對應(yīng)的文件中鸥印。
// 案例5:
#include<stdio.h>
int main()
{
FILE* fp = fopen("./text","r");
if (NULL == fp)
{
printf("cann't open the file\n");
exit(1);
}
char ch;
// 讀取文件中的字符,一個一個的讀取坦报。
ch = fgetc(fp);
while (EOF != ch) // EOF表示讀到文件的末尾
{
printf("%c\n",ch);
ch = fgetc(fp);
}
close(fp);
// 向文件中寫入數(shù)據(jù)
fp = fopen("./text1","w");
if (NULL == fp)
{
printf("cann't open the file\n");
exit(1);
}
printf("input a character:");
scanf("%c",&ch);
fputc(ch,fp); // 將ch變量中的字符存放到文件“./text1”中库说。
return 0;
}
注意:在網(wǎng)文件中寫數(shù)據(jù)的時候,上的那種寫法是片择,直接覆蓋文件中的數(shù)據(jù)潜的,而不是在文件的末尾追加數(shù)據(jù)。若想不改變文件原來的數(shù)據(jù)字管,只想在文件的末尾追加數(shù)據(jù)啰挪,那么需要將文件的打開方式“w”更改為“a”,這樣我們就可以在原數(shù)據(jù)的基礎(chǔ)上追加數(shù)據(jù)纤掸。
2. 字符串讀寫函數(shù)fgets 和 fputs
fgets() 的一般形式:
fgets(字符數(shù)組名脐供,n,文件指針)借跪;
說明:n是一個正整數(shù)政己,表示從文件中讀取的字符串不超過n-1個字符,在讀入最后一個字符后加上結(jié)束符'\0'掏愁。
fputs()的一般形式:
fputs(字符數(shù)組名歇由,文件指針);
說明:字符數(shù)組名果港,首先其中必須是一個已被初始化的字符數(shù)組沦泌,即里面有值;也可以用一個字符串常量(或指針變量)代替字符數(shù)組名辛掠。
//案例6:
#include<stdio.h>
int main()
{
char ch[20];
FILE *fp = fopen("./text","rw");
if (NULL == fp)
{
printf("open error\n");
exit(1);
}
printf("input what you want to say:");
scanf("%s",ch);
//將字符串ch中的值寫在文件text中谢谦。
fputs(ch,fp);
char ch2[30];
// 從文件中讀取數(shù)據(jù),并由ch2字符串變量接收萝衩。
fgets(ch2,sizeof(ch2)-1,fp);
printf("ch2:%s\n",ch2);
return 0;
}
3. 數(shù)據(jù)塊讀寫函數(shù)fread 和fwrite
C語言中不僅提供了字符回挽、字符串的讀寫方式,同時也提供了數(shù)據(jù)塊的讀寫方式猩谊。它們可用來讀寫一組數(shù)據(jù)千劈,如:一個數(shù)組元素,一個結(jié)構(gòu)變量的值等牌捷。
fread()的一般形式:
fread(buffer墙牌,size涡驮,count,fp);
fwrite()的一般形式:
fwrite(buffer喜滨,size捉捅,count,fp)鸿市;
說明:
- buffer 是一個指針锯梁,在fread函數(shù)中表示存放數(shù)據(jù)的首地址即碗。在fwrite函數(shù)中表示輸出數(shù)據(jù)的首地址焰情;
- size 表示數(shù)據(jù)塊的字節(jié)數(shù);
- count 表示要讀寫的數(shù)據(jù)塊的塊數(shù)
- fp 表示文件的指針
//案例7:
#include<stdio.h>
struct student
{
int id;
char name[20];
float score;
};
int main()
{
struct student boy[2];
int i = 0;
for (;i < 2; i++)
{
printf("input the student's infomation(id, name, score):");
scanf("%d%s%f",&boy[i]->id,boy[i]->name,&boy[i]->score);
}
FILE* fp;
fp = fopen("./student.text","w+");
if (NULL == fp)
{
printf("open file error\n");
exit(1);
}
fwrite(boy,sizeof(struct student),2,fp);
rewind(fp);
struct student stu[2];
fread(stu,sizeof(struct student),2,fp);
printf("id\tname\tscore\n");
for (i = 0; i < 2; i++)
{
printf("%d\t%s\t%f\n",stu[i]->id,stu[i]->name,stu[i]->score);
}
return 0;
}
4. 格式化讀寫函數(shù)fscanf 和 fprintf
fscanf剥懒、fprintf和scanf内舟、printf的區(qū)別:
fscanf和fprintf函數(shù)的讀寫不是對鍵盤和顯示器的,而是對磁盤文件初橘;不過它們都是格式化讀寫函數(shù)验游。
fscanf 的一般形式:
fscanf(文件指針, 格式字符串保檐, 輸入列表)耕蝉;
fprintf 的一般形式:
fprintf(文件指針, 格式字符串夜只, 輸出列表)垒在;
//案例8:
#include<stdio.h>
int main()
{
char caBuf[3][32] = {'\0'};
int i = 0;
for (; i < 3; i++)
{
printf("input :");
scanf("%s", caBuf[i]);
}
FILE *fp;
fp = fopen("./MyInput", "wb+");
if (NULL == fp)
{
printf("open file error\n");
exit(1);
}
for (i=0; i < 3; i++)
{
fprintf(fp, "%s", caBuf[i]);
}
rewind(fp);
char sMsg[32] = {'\0'};
for(i=0; i < 3; i++)
{
fscanf(fp, "%s", sMsg);
printf("sMsg: %s\n", sMsg);
}
fclose(fp);
return 0;
}
文件定位
有的時候我們在讀寫文件時,不想從開頭或者末尾開始讀或者寫扔亥;想讀取中間的內(nèi)容场躯,或者是想將一段數(shù)據(jù)插入到文件中間,我們該怎么做旅挤?這時候踢关,我們就需要引入新的知識,文件的定位粘茄。
文件定位函數(shù)
在文件定位中签舞,主要有兩個函數(shù):rewind()和fseek().
rewind() 在前面已經(jīng)使用,并進行一定的說明柒瓣,不過在這里還是要重申一下儒搭,其一般形式為:
rewind(文件指針);
功能:文件內(nèi)部的文件指針轉(zhuǎn)移到文件首部嘹朗。
fseek() 的一般形式:
fseek(文件指針师妙, 位移量, 起始點);
參數(shù)說明:
文件指針:被指向移動的文件屹培;
位移量:表示移動的字節(jié)數(shù)默穴;
起始點:表示從何處開始計算位移量怔檩,規(guī)定有三種:文件首部(SEEK_SET,1)蓄诽,當(dāng)前位置(SEEK_CUR薛训,0)和文件尾部(SEEK_END, 2)仑氛。
// 案例10:
fseek(fp, 100, 0);
//表示:把文件位置指針移到距離首部100個字節(jié)處乙埃。
注意事項:fseek()一般用于二進制文件。在文本文件中由于要進行轉(zhuǎn)換锯岖,故往往計算位置會出現(xiàn)錯誤