?? 13.txt
字號(hào):
13 文件 1
13.1 C文件概述 1
13.2 文件指針 2
13.3 文件的打開(kāi)與關(guān)閉 2
13.3.1 文件的打開(kāi)(fopen函數(shù)) 2
13.3.2 文件關(guān)閉函數(shù)(fclose函數(shù)) 4
13.4 文件的讀寫 4
13.4.1 字符讀寫函數(shù)fgetc和fputc 4
13.4.2 字符串讀寫函數(shù)fgets和fputs 8
13.4.3 數(shù)據(jù)塊讀寫函數(shù)fread和fwtrite 9
13.4.4 格式化讀寫函數(shù)fscanf和fprintf 11
13.5 文件的隨機(jī)讀寫 12
13.5.1 文件定位 12
13.5.2 文件的隨機(jī)讀寫 13
13.6 文件檢測(cè)函數(shù) 14
13.6.1 文件結(jié)束檢測(cè)函數(shù)feof函數(shù) 14
13.6.2 讀寫文件出錯(cuò)檢測(cè)函數(shù) 14
13.6.3 文件出錯(cuò)標(biāo)志和文件結(jié)束標(biāo)志置0函數(shù) 14
13.7 C庫(kù)文件 14
13.8 本章小結(jié) 15
13 文件
13.1 C文件概述
所謂“文件”是指一組相關(guān)數(shù)據(jù)的有序集合。這個(gè)數(shù)據(jù)集有一個(gè)名稱,叫做文件名。實(shí)際上在前面的各章中我們已經(jīng)多次使用了文件,例如源程序文件、目標(biāo)文件、可執(zhí)行文件、庫(kù)文件 (頭文件)等。
文件通常是駐留在外部介質(zhì)(如磁盤等)上的,在使用時(shí)才調(diào)入內(nèi)存中來(lái)。從不同的角度可對(duì)文件作不同的分類。從用戶的角度看,文件可分為普通文件和設(shè)備文件兩種。
普通文件是指駐留在磁盤或其它外部介質(zhì)上的一個(gè)有序數(shù)據(jù)集,可以是源文件、目標(biāo)文件、可執(zhí)行程序;也可以是一組待輸入處理的原始數(shù)據(jù),或者是一組輸出的結(jié)果。對(duì)于源文件、目標(biāo)文件、可執(zhí)行程序可以稱作程序文件,對(duì)輸入輸出數(shù)據(jù)可稱作數(shù)據(jù)文件。
設(shè)備文件是指與主機(jī)相聯(lián)的各種外部設(shè)備,如顯示器、打印機(jī)、鍵盤等。在操作系統(tǒng)中,把外部設(shè)備也看作是一個(gè)文件來(lái)進(jìn)行管理,把它們的輸入、輸出等同于對(duì)磁盤文件的讀和寫。
通常把顯示器定義為標(biāo)準(zhǔn)輸出文件,一般情況下在屏幕上顯示有關(guān)信息就是向標(biāo)準(zhǔn)輸出文件輸出。如前面經(jīng)常使用的printf,putchar函數(shù)就是這類輸出。
鍵盤通常被指定標(biāo)準(zhǔn)的輸入文件,從鍵盤上輸入就意味著從標(biāo)準(zhǔn)輸入文件上輸入數(shù)據(jù)。scanf,getchar函數(shù)就屬于這類輸入。
從文件編碼的方式來(lái)看,文件可分為ASCII碼文件和二進(jìn)制碼文件兩種。ASCII文件也稱為文本文件,這種文件在磁盤中存放時(shí)每個(gè)字符對(duì)應(yīng)一個(gè)字節(jié),用于存放對(duì)應(yīng)的ASCII碼。
例如,數(shù)5678的存儲(chǔ)形式為:
ASCII碼: 00110101 00110110 00110111 00111000
↓ ↓ ↓ ↓
十進(jìn)制碼: 5 6 7 8
共占用4個(gè)字節(jié)。
ASCII碼文件可在屏幕上按字符顯示,例如源程序文件就是ASCII文件,用DOS命令TYPE可顯示文件的內(nèi)容。由于是按字符顯示,因此能讀懂文件內(nèi)容。
二進(jìn)制文件是按二進(jìn)制的編碼方式來(lái)存放文件的。
例如, 數(shù)5678的存儲(chǔ)形式為:
00010110 00101110
只占二個(gè)字節(jié)。二進(jìn)制文件雖然也可在屏幕上顯示,但其內(nèi)容無(wú)法讀懂。C系統(tǒng)在處理這些文件時(shí),并不區(qū)分類型,都看成是字符流,按字節(jié)進(jìn)行處理。
輸入輸出字符流的開(kāi)始和結(jié)束只由程序控制而不受物理符號(hào)(如回車符)的控制。 因此也把這種文件稱作“流式文件”。
本章討論流式文件的打開(kāi)、關(guān)閉、讀、寫、 定位等各種操作。
13.1 文件指針
在C語(yǔ)言中用一個(gè)指針變量指向一個(gè)文件,這個(gè)指針?lè)Q為文件指針。通過(guò)文件指針就可對(duì)它所指的文件進(jìn)行各種操作。
定義說(shuō)明文件指針的一般形式為:
FILE *指針變量標(biāo)識(shí)符;
其中FILE應(yīng)為大寫,它實(shí)際上是由系統(tǒng)定義的一個(gè)結(jié)構(gòu),該結(jié)構(gòu)中含有文件名、文件狀態(tài)和文件當(dāng)前位置等信息。在編寫源程序時(shí)不必關(guān)心FILE結(jié)構(gòu)的細(xì)節(jié)。
例如:
FILE *fp;
表示fp是指向FILE結(jié)構(gòu)的指針變量,通過(guò)fp即可找存放某個(gè)文件信息的結(jié)構(gòu)變量,然后按結(jié)構(gòu)變量提供的信息找到該文件,實(shí)施對(duì)文件的操作。習(xí)慣上也籠統(tǒng)地把fp稱為指向一個(gè)文件的指針。
13.2 文件的打開(kāi)與關(guān)閉
文件在進(jìn)行讀寫操作之前要先打開(kāi),使用完畢要關(guān)閉。所謂打開(kāi)文件,實(shí)際上是建立文件的各種有關(guān)信息,并使文件指針指向該文件,以便進(jìn)行其它操作。關(guān)閉文件則斷開(kāi)指針與文件之間的聯(lián)系,也就禁止再對(duì)該文件進(jìn)行操作。
在C語(yǔ)言中,文件操作都是由庫(kù)函數(shù)來(lái)完成的。在本章內(nèi)將介紹主要的文件操作函數(shù)。
13.2.1 文件的打開(kāi)(fopen函數(shù))
fopen函數(shù)用來(lái)打開(kāi)一個(gè)文件,其調(diào)用的一般形式為:
文件指針名=fopen(文件名,使用文件方式);
其中,
“文件指針名”必須是被說(shuō)明為FILE 類型的指針變量;
“文件名”是被打開(kāi)文件的文件名;
“使用文件方式”是指文件的類型和操作要求。
“文件名”是字符串常量或字符串?dāng)?shù)組。
例如:
FILE *fp;
fp=("file a","r");
其意義是在當(dāng)前目錄下打開(kāi)文件file a,只允許進(jìn)行“讀”操作,并使fp指向該文件。
又如:
FILE *fphzk
fphzk=("c:\\hzk16","rb")
其意義是打開(kāi)C驅(qū)動(dòng)器磁盤的根目錄下的文件hzk16,這是一個(gè)二進(jìn)制文件,只允許按二進(jìn)制方式進(jìn)行讀操作。兩個(gè)反斜線“\\ ”中的第一個(gè)表示轉(zhuǎn)義字符,第二個(gè)表示根目錄。
使用文件的方式共有12種,下面給出了它們的符號(hào)和意義。
文件使用方式 意義
“rt” 只讀打開(kāi)一個(gè)文本文件,只允許讀數(shù)據(jù)
“wt” 只寫打開(kāi)或建立一個(gè)文本文件,只允許寫數(shù)據(jù)
“at” 追加打開(kāi)一個(gè)文本文件,并在文件末尾寫數(shù)據(jù)
“rb” 只讀打開(kāi)一個(gè)二進(jìn)制文件,只允許讀數(shù)據(jù)
“wb” 只寫打開(kāi)或建立一個(gè)二進(jìn)制文件,只允許寫數(shù)據(jù)
“ab” 追加打開(kāi)一個(gè)二進(jìn)制文件,并在文件末尾寫數(shù)據(jù)
“rt+” 讀寫打開(kāi)一個(gè)文本文件,允許讀和寫
“wt+” 讀寫打開(kāi)或建立一個(gè)文本文件,允許讀寫
“at+” 讀寫打開(kāi)一個(gè)文本文件,允許讀,或在文件末追加數(shù)據(jù)
“rb+” 讀寫打開(kāi)一個(gè)二進(jìn)制文件,允許讀和寫
“wb+” 讀寫打開(kāi)或建立一個(gè)二進(jìn)制文件,允許讀和寫
“ab+” 讀寫打開(kāi)一個(gè)二進(jìn)制文件,允許讀,或在文件末追加數(shù)據(jù)
對(duì)于文件使用方式有以下幾點(diǎn)說(shuō)明:
1) 文件使用方式由r,w,a,t,b,+六個(gè)字符拼成,各字符的含義是:
r(read): 讀
w(write): 寫
a(append): 追加
t(text): 文本文件,可省略不寫
b(banary): 二進(jìn)制文件
+: 讀和寫
2) 凡用“r”打開(kāi)一個(gè)文件時(shí),該文件必須已經(jīng)存在,且只能從該文件讀出。
3) 用“w”打開(kāi)的文件只能向該文件寫入。若打開(kāi)的文件不存在,則以指定的文件名建立該文件,若打開(kāi)的文件已經(jīng)存在,則將該文件刪去,重建一個(gè)新文件。
4) 若要向一個(gè)已存在的文件追加新的信息,只能用“a”方式打開(kāi)文件。但此時(shí)該文件必須是存在的,否則將會(huì)出錯(cuò)。
5) 在打開(kāi)一個(gè)文件時(shí),如果出錯(cuò),fopen將返回一個(gè)空指針值NULL。在程序中可以用這一信息來(lái)判別是否完成打開(kāi)文件的工作,并作相應(yīng)的處理。因此常用以下程序段打開(kāi)文件:
6) if((fp=fopen("c:\\hzk16","rb")==NULL)
{
printf("\nerror on open c:\\hzk16 file!");
getch();
exit(1);
}
這段程序的意義是,如果返回的指針為空,表示不能打開(kāi)C盤根目錄下的hzk16文件,則給出提示信息“error on open c:\ hzk16 file!”,下一行g(shù)etch()的功能是從鍵盤輸入一個(gè)字符,但不在屏幕上顯示。在這里,該行的作用是等待,只有當(dāng)用戶從鍵盤敲任一鍵時(shí),程序才繼續(xù)執(zhí)行,因此用戶可利用這個(gè)等待時(shí)間閱讀出錯(cuò)提示。敲鍵后執(zhí)行exit(1)退出程序。
7) 把一個(gè)文本文件讀入內(nèi)存時(shí),要將ASCII碼轉(zhuǎn)換成二進(jìn)制碼,而把文件以文本方式寫入磁盤時(shí),也要把二進(jìn)制碼轉(zhuǎn)換成ASCII碼,因此文本文件的讀寫要花費(fèi)較多的轉(zhuǎn)換時(shí)間。對(duì)二進(jìn)制文件的讀寫不存在這種轉(zhuǎn)換。
8) 標(biāo)準(zhǔn)輸入文件(鍵盤),標(biāo)準(zhǔn)輸出文件(顯示器),標(biāo)準(zhǔn)出錯(cuò)輸出(出錯(cuò)信息)是由系統(tǒng)打開(kāi)的,可直接使用。
13.2.2 文件關(guān)閉函數(shù)(fclose函數(shù))
文件一旦使用完畢,應(yīng)用關(guān)閉文件函數(shù)把文件關(guān)閉,以避免文件的數(shù)據(jù)丟失等錯(cuò)誤。
fclose函數(shù)調(diào)用的一般形式是:
fclose(文件指針);
例如:
fclose(fp);
正常完成關(guān)閉文件操作時(shí),fclose函數(shù)返回值為0。如返回非零值則表示有錯(cuò)誤發(fā)生。
13.3 文件的讀寫
對(duì)文件的讀和寫是最常用的文件操作。在C語(yǔ)言中提供了多種文件讀寫的函數(shù):
?字符讀寫函數(shù) :fgetc和fputc
?字符串讀寫函數(shù):fgets和fputs
?數(shù)據(jù)塊讀寫函數(shù):freed和fwrite
?格式化讀寫函數(shù):fscanf和fprinf
下面分別予以介紹。使用以上函數(shù)都要求包含頭文件stdio.h。
13.3.1 字符讀寫函數(shù)fgetc和fputc
字符讀寫函數(shù)是以字符(字節(jié))為單位的讀寫函數(shù)。 每次可從文件讀出或向文件寫入一個(gè)字符。
1. 讀字符函數(shù)fgetc
fgetc函數(shù)的功能是從指定的文件中讀一個(gè)字符,函數(shù)調(diào)用的形式為:
字符變量=fgetc(文件指針);
例如:
ch=fgetc(fp);
其意義是從打開(kāi)的文件fp中讀取一個(gè)字符并送入ch中。
對(duì)于fgetc函數(shù)的使用有以下幾點(diǎn)說(shuō)明:
1) 在fgetc函數(shù)調(diào)用中,讀取的文件必須是以讀或讀寫方式打開(kāi)的。
2) 讀取字符的結(jié)果也可以不向字符變量賦值,
例如:
fgetc(fp);
但是讀出的字符不能保存。
3) 在文件內(nèi)部有一個(gè)位置指針。用來(lái)指向文件的當(dāng)前讀寫字節(jié)。在文件打開(kāi)時(shí),該指針總是指向文件的第一個(gè)字節(jié)。使用fgetc 函數(shù)后,該位置指針將向后移動(dòng)一個(gè)字節(jié)。 因此可連續(xù)多次使用fgetc函數(shù),讀取多個(gè)字符。應(yīng)注意文件指針和文件內(nèi)部的位置指針不是一回事。文件指針是指向整個(gè)文件的,須在程序中定義說(shuō)明,只要不重新賦值,文件指針的值是不變的。文件內(nèi)部的位置指針用以指示文件內(nèi)部的當(dāng)前讀寫位置,每讀寫一次,該指針均向后移動(dòng),它不需在程序中定義說(shuō)明,而是由系統(tǒng)自動(dòng)設(shè)置的。
【例13.1】讀入文件c1.doc,在屏幕上輸出。
#include<stdio.h>
main()
{
FILE *fp;
char ch;
if((fp=fopen("d:\\jrzh\\example\\c1.txt","rt"))==NULL)
{
printf("\nCannot open file strike any key exit!");
getch();
exit(1);
}
ch=fgetc(fp);
while(ch!=EOF)
{
putchar(ch);
ch=fgetc(fp);
}
fclose(fp);
}
本例程序的功能是從文件中逐個(gè)讀取字符,在屏幕上顯示。程序定義了文件指針fp,以讀文本文件方式打開(kāi)文件“d:\\jrzh\\example\\ex1_1.c”,并使fp指向該文件。如打開(kāi)文件出錯(cuò),給出提示并退出程序。程序第12行先讀出一個(gè)字符,然后進(jìn)入循環(huán),只要讀出的字符不是文件結(jié)束標(biāo)志(每個(gè)文件末有一結(jié)束標(biāo)志EOF)就把該字符顯示在屏幕上,再讀入下一字符。每讀一次,文件內(nèi)部的位置指針向后移動(dòng)一個(gè)字符,文件結(jié)束時(shí),該指針指向EOF。執(zhí)行本程序?qū)@示整個(gè)文件。
2. 寫字符函數(shù)fputc
fputc函數(shù)的功能是把一個(gè)字符寫入指定的文件中,函數(shù)調(diào)用的形式為:
fputc(字符量,文件指針);
其中,待寫入的字符量可以是字符常量或變量,例如:
fputc('a',fp);
其意義是把字符a寫入fp所指向的文件中。
對(duì)于fputc函數(shù)的使用也要說(shuō)明幾點(diǎn):
1) 被寫入的文件可以用寫、讀寫、追加方式打開(kāi),用寫或讀寫方式打開(kāi)一個(gè)已存在的文件時(shí)將清除原有的文件內(nèi)容,寫入字符從文件首開(kāi)始。如需保留原有文件內(nèi)容,希望寫入的字符以文件末開(kāi)始存放,必須以追加方式打開(kāi)文件。被寫入的文件若不存在,則創(chuàng)建該文件。
2) 每寫入一個(gè)字符,文件內(nèi)部位置指針向后移動(dòng)一個(gè)字節(jié)。
3) fputc函數(shù)有一個(gè)返回值,如寫入成功則返回寫入的字符,否則返回一個(gè)EOF。可用此來(lái)判斷寫入是否成功。
【例13.2】從鍵盤輸入一行字符,寫入一個(gè)文件,再把該文件內(nèi)容讀出顯示在屏幕上。
#include<stdio.h>
main()
{
FILE *fp;
char ch;
if((fp=fopen("d:\\jrzh\\example\\string","wt+"))==NULL)
{
printf("Cannot open file strike any key exit!");
getch();
exit(1);
}
printf("input a string:\n");
ch=getchar();
while (ch!='\n')
{
fputc(ch,fp);
ch=getchar();
}
rewind(fp);
ch=fgetc(fp);
while(ch!=EOF)
{
putchar(ch);
ch=fgetc(fp);
}
printf("\n");
fclose(fp);
}
程序中第6行以讀寫文本文件方式打開(kāi)文件string。程序第13行從鍵盤讀入一個(gè)字符后進(jìn)入循環(huán),當(dāng)讀入字符不為回車符時(shí),則把該字符寫入文件之中,然后繼續(xù)從鍵盤讀入下一字符。每輸入一個(gè)字符,文件內(nèi)部位置指針向后移動(dòng)一個(gè)字節(jié)。寫入完畢,該指針已指向文件末。如要把文件從頭讀出,須把指針移向文件頭,程序第19行rewind函數(shù)用于把fp所指文件的內(nèi)部位置指針移到文件頭。第20至25行用于讀出文件中的一行內(nèi)容。
【例13.3】把命令行參數(shù)中的前一個(gè)文件名標(biāo)識(shí)的文件,復(fù)制到后一個(gè)文件名標(biāo)識(shí)的文件中, 如命令行中只有一個(gè)文件名則把該文件寫到標(biāo)準(zhǔn)輸出文件(顯示器)中。
#include<stdio.h>
main(int argc,char *argv[])
{
FILE *fp1,*fp2;
char ch;
if(argc==1)
{
printf("have not enter file name strike any key exit");
getch();
exit(0);
}
if((fp1=fopen(argv[1],"rt"))==NULL)
{
printf("Cannot open %s\n",argv[1]);
getch();
exit(1);
}
if(argc==2) fp2=stdout;
else if((fp2=fopen(argv[2],"wt+"))==NULL)
{
printf("Cannot open %s\n",argv[1]);
getch();
exit(1);
}
while((ch=fgetc(fp1))!=EOF)
fputc(ch,fp2);
fclose(fp1);
fclose(fp2);
}
本程序?yàn)閹⒌膍ain函數(shù)。程序中定義了兩個(gè)文件指針fp1和fp2,分別指向命令行參數(shù)中給出的文件。如命令行參數(shù)中沒(méi)有給出文件名,則給出提示信息。程序第18行表示如果只給出一個(gè)文件名,則使fp2指向標(biāo)準(zhǔn)輸出文件(即顯示器)。程序第25行至28行用循環(huán)語(yǔ)句逐個(gè)讀出文件1中的字符再送到文件2中。再次運(yùn)行時(shí),給出了一個(gè)文件名,故輸出給標(biāo)準(zhǔn)輸出文件stdout,即在顯示器上顯示文件內(nèi)容。第三次運(yùn)行,給出了二個(gè)文件名,因此把string中的內(nèi)容讀出,寫入到OK之中。可用DOS命令type顯示OK的內(nèi)容。
13.3.2 字符串讀寫函數(shù)fgets和fputs
1. 讀字符串函數(shù)fgets
函數(shù)的功能是從指定的文件中讀一個(gè)字符串到字符數(shù)組中,函數(shù)調(diào)用的形式為:
fgets(字符數(shù)組名,n,文件指針);
其中的n是一個(gè)正整數(shù)。表示從文件中讀出的字符串不超過(guò) n-1個(gè)字符。在讀入的最后一個(gè)字符后加上串結(jié)束標(biāo)志'\0'。
例如:
fgets(str,n,fp);
的意義是從fp所指的文件中讀出n-1個(gè)字符送入字符數(shù)組str中。
【例13.4】從string文件中讀入一個(gè)含10個(gè)字符的字符串。
#include<stdio.h>
main()
{
FILE *fp;
char str[11];
if((fp=fopen("d:\\jrzh\\example\\string","rt"))==NULL)
{
printf("\nCannot open file strike any key exit!");
getch();
exit(1);
}
fgets(str,11,fp);
printf("\n%s\n",str);
fclose(fp);
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -