版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第9章文件處理
9.1C語言中的文件9.2文件類型指針9.3文件操作9.1C語言中的文件
C語言中的文件為流式文件,即把文件看作是一個有序的字符流。每個文件或者以文件結(jié)束標志結(jié)束,或者在特定的字節(jié)號處結(jié)束(這個特定的字節(jié)號登記在由系統(tǒng)維護和管理的數(shù)據(jù)結(jié)構(gòu)中),如圖9―1所示。圖9―1由n個字符構(gòu)成的字符流(c文件)當打開一個文件的時候,該文件就和某個流關(guān)聯(lián)起來。執(zhí)行程序會自動打開三個標準文件——標準輸入文件、標準輸出文件和標準錯誤文件以及與這三個文件相連的三種流——標準輸入流、標準輸出流和標準錯誤流。流是文件和數(shù)據(jù)之間通信的通道。圖9―2兩種文件形式與內(nèi)存形式之間的關(guān)系由圖9―2可以看出,二進制文件的好處是:占用存儲空間少;文件形式和內(nèi)存形式一致,不需要轉(zhuǎn)換,因而處理起來速度快。我們還應(yīng)該了解一下操作系統(tǒng)對文件處理的方式。C語言目前使用的磁盤文件系統(tǒng)主要是“緩沖文件系統(tǒng)”,所謂緩沖文件系統(tǒng)是指在程序的數(shù)據(jù)區(qū)和磁盤文件之間并不是直接通信的,而是通過緩沖區(qū)相聯(lián)系的。所謂緩沖區(qū),實際上也是內(nèi)存中的一空間。在輸入數(shù)據(jù)時,先把數(shù)據(jù)從磁盤讀到“輸入緩沖區(qū)”中,等輸入緩沖區(qū)已滿或強制把它清空時再把其中的數(shù)據(jù)送到數(shù)據(jù)區(qū)進行處理。處理后的數(shù)據(jù)要送入文件保存,但這也不是隨處理隨傳送的,而是先放到“輸出緩沖區(qū)”,等輸出緩沖區(qū)已滿或強制將其清空時再把其中的數(shù)據(jù)送到磁盤文件。也就是說不一定每執(zhí)行一次輸入/輸出語句就實際訪問磁盤文件一次,而是多次讀寫對應(yīng)一次磁盤訪問。緩沖區(qū)的大小隨機器而異,且由系統(tǒng)自動設(shè)置,其大小一般為512字節(jié)或其整數(shù)倍。緩沖文件系統(tǒng)的示意圖如圖9―3所示。
圖9―3緩沖文件系統(tǒng)示意圖9.2文件類型指針文件指針在緩沖文件系統(tǒng)中處理磁盤文件時有重要的作用。要運行一個文件,必須知道與該文件有關(guān)的信息,比如文件名,文件狀態(tài),文件當前的讀寫位置,文件緩沖區(qū)的大小與位置等等。這些信息被系統(tǒng)保存在一個結(jié)構(gòu)體中,這個結(jié)構(gòu)體中的信息組成了文件類型。系統(tǒng)為該類型起了個專用的名字:FILE。FILE類型的結(jié)構(gòu)和操作系統(tǒng)有關(guān),也就是說該結(jié)構(gòu)的成員隨系統(tǒng)對文件處理的方式的不同而不同。TurboC系統(tǒng)的文件結(jié)構(gòu)類型為:
typedef
struct{
intlevel;/*緩沖區(qū)被占用的程度*/ unsignedflags;/*文件狀態(tài)標記*/charfd;/*文件描述符*/unsignedcharhold;/*如無緩沖區(qū),則不讀取字符*/
int
bsize;/*緩沖區(qū)大小*/unsignedchar*buffer;/*文件緩沖區(qū)指針*/unsignedchar*curp;/*文件定位指針*/unsignedistemp;/*暫時文件指示器*/shorttoken;/*用于有效性檢查*/}FILE;
C語言程序要求,在對一個文件進行處理時,需首先定義一個FILE類型的指針,即建立一個FILE類型的指針變量,該指針變量用于指向系統(tǒng)內(nèi)存中的一個FILE類型的結(jié)構(gòu)體(即文件信息區(qū)),結(jié)構(gòu)體中保存著當前處理文件的相關(guān)信息。文件指針的定義形式為:
FILE*<文件指針名>
例如:
FILE*fp1,*fp2,*fp[3];則文件指針fp1和fp2可以指向某個文件結(jié)構(gòu)體而訪問該文件。文件指針數(shù)組fp中有3個文件的信息。9.3文件操作
9.3.1文件的打開與關(guān)閉文件在使用之前必須打開,處理完之后必須關(guān)閉。
1.文件的打開文件的打開是由調(diào)用fopen函數(shù)實現(xiàn)的,其格式為:
<文件指針>=fopen(<文件名>,<打開方式>)<文件指針>即類型為FILE的指針變量;<文件名>為DOS文件名,是一個字符串;<打開方式>也是個字符串,指出文件打開的目的。文件的打開方式列于表9―1中,其中列出了各種文件的打開方式,隱含的是打開ASCII文件,如果打開的是二進制文件,則增加一個字符b(binary)。其他字符的含義為:r代表read,用于讀;w代表write,用于寫;a代表append,用于追加。表9―1文件的打開方式說明:
(1)凡是打開方式字符串中含有字符“r”的,所打開的文件必須是已存在的文件,對不存在的文件不能打開讀。
(2)凡是打開方式中帶有“w”字符的,所打開的文件可以是已經(jīng)存在的,也可以是尚不存在的。若不存在時,則先要建立一個新文件,然后在里面寫內(nèi)容;若文件已經(jīng)存在,則會把原文件的內(nèi)容覆蓋掉,寫入新的內(nèi)容。
(3)凡含有字符“a”,以追加方式打開的文件也可以不存在,若不存在則建立一個新文件后再追加;若已存在,則在文件的尾部追加。
(4)以“r+”和“w+”方式打開的文件都是既可用于讀,又可用于寫的。其差別是,以“w+”方式打開的是一個新文件,應(yīng)先寫入內(nèi)容,然后可以讀。
(5)在打開文件的操作中有可能出現(xiàn)故障,如當文件所在的磁盤未準備好時,不能把文件打開,這時打開文件函數(shù)fopen就返回NULL值。
(6)有三個和標準輸入/輸出流對應(yīng)的設(shè)備文件不需用戶打開,在執(zhí)行程序時,系統(tǒng)自動將它們打開。這三個文件是標準輸入文件、標準輸出文件和標準出錯文件,指向它們的文件指針分別是stdin、stdout和stderr。
2.文件的關(guān)閉文件使用后必須及時關(guān)閉,以保護其中的數(shù)據(jù)。關(guān)閉就是使文件指針不再指向該文件,它可以再去指向其他文件。關(guān)閉文件的操作還有一個作用是清除緩沖區(qū)。在文件處理的最后,緩沖區(qū)中可能尚有一些數(shù)據(jù),關(guān)閉操作首先把這些數(shù)據(jù)送入磁盤文件,然后再釋放文件指針。因此,如果不關(guān)閉文件,則留在緩沖區(qū)中的數(shù)據(jù)就會丟失。關(guān)閉文件用fclose函數(shù),其格式為:
fclose(<文件指針名>)
9.3.2文件的輸入和輸出文件的輸入/輸出操作一般是按以下步驟進行的:
(1)用fopen函數(shù)打開文件;
(2)對文件進行讀/寫操作;
(3)用fclose函數(shù)關(guān)閉文件。對已打開的文件的輸入/輸出操作是通過文件指針進行的,實際上是由一些標準的讀/寫函數(shù)完成的。所謂文件的輸入是指用一些具有讀功能的函數(shù)把磁盤文件中的數(shù)據(jù)讀入內(nèi)存;所謂文件的輸出是指用一些具有寫功能的函數(shù)把內(nèi)存中的數(shù)據(jù)寫入磁盤文件。
1.文件的字符輸入/輸出函數(shù)fgetc和fputc1)fgetc函數(shù)
fgetc函數(shù)的調(diào)用格式為:
<字符變量>=fgetc(<文件指針>)
功能:從<文件指針>所指的文件中讀入一個字符賦給<字符變量>(在內(nèi)存中)。
2)fputc函數(shù)設(shè)ch為字符類型,則其調(diào)用格式為:
fputc(ch,<文件指針>)
功能:把字符ch(變量或常量)放入<文件指針>所指的文件中。如果操作失敗,則返回一個EOF。如果文件指針為標準輸出文件指針stdout,則有:
fputc(ch,stdout)=putchar(ch)
這也在頭文件<stdio.h>中作了宏定義:#defineputchar(ch)fputc(ch,stdout)
對標準輸入/輸出文件而言,用getchar()和putchar()更為簡單。
3)用字符輸入輸出函數(shù)處理文件
【例9―1】文本文件復(fù)制。把文件c:\f1.bat進行復(fù)制,新文件為a:\f2.bat。#include<stdio.h>main(){FILE*fp1,*fp2;charc;if(((fp1=fopen(″c:\\f1.bat″,″r″))==NULL)||((fp2=fopen(″a:\\f2.bat″,″w″))==NULL))
{printf(″openfail\n″); exit(0);}while(!feof(fp1)){c=fgetc(fp1);fputc(c,fp2);}fclose(fp1);fclose(fp2);return0;}該程序是把c盤上的批處理文件拷貝到a盤上。c盤上的文件作為數(shù)據(jù)的提供者,以“r”方式打開;a盤上的文件作為數(shù)據(jù)接收者,以“w”方式打開。while(!feof(fp1))等價于while(feof(fp1)==0),即文件fp1未結(jié)束。
【例9―2】實現(xiàn)操作系統(tǒng)命令提示符下的文件連接功能,如
c:\>appendfile1file2
命令實現(xiàn)把文件file1追加到文件file2的末尾。程序如下:#include<stdio.h>
main(int
argc,char*argv[]){FILE*fp1,*fp2;
intc;
if(argc!=3) {printf(″USAGE:file1file2\n″);
exit(0);}if(((fp1=fopen(argv[1],″r″))=NULL)||;((fp2=fopen(argv[2],″a″))==NULL)){printf(″Openfail\n″);exit(0);}
while((c=fgetc(fp1))!=EOF)fputc(c,fp2);
fclose(fp1);fclose(fp2);return0;}
2.文件的字符串輸入/輸出函數(shù)fgets()和fputs()1)fgets()函數(shù)
fgets函數(shù)的調(diào)用格式為:
fgets(str,n,fp)
其中,str為指定的字符數(shù)組;n為包括“\0”字符在內(nèi)的字符個數(shù);fp為文件指針。
功能:從fp所指文件中讀取n-1個字符(留一個字符給′\0′),并把它們放入str字符數(shù)組中。當滿足下列條件之一時,讀取結(jié)束:
(1)已經(jīng)讀取了n-1個字符;
(2)當前讀到的字符為回車符;
(3)已讀到文件的末尾。
2)fputs函數(shù)
fputs函數(shù)的調(diào)用格式為:
fputs(str,fp)
其中,fp為文件指針,str為一字符串,它可以是指向字符串的指針,也可以是字符數(shù)組名,還可以是字符串常量。功能:把指定的字符串放到指定的文件中。
fputs函數(shù)在將字符串寫入文件時,把字符串后的′\0′字符自動舍去。同樣的,
fputs(str,stdout)≠puts(str)
因為puts()函數(shù)是把字符串尾部的′\0′字符變成回車符輸出,而fputs函數(shù)則是舍去字符串末尾的′\0′字符。
fputs函數(shù)若輸出成功,返回值為0;若輸出失敗,返回值為EOF(即-1)。【例9―3】#include<stdio.h>main(){ charstr[10];
gets(str);
puts(str);
puts(str);
putchar(′\n′);
fputs(str,stdout);
fputs(str,stdout); return0;};運行輸出:
very/*輸入*/very/*兩個puts的輸出*/very
veryvery/*兩個fputs的輸出*/
分析運行結(jié)果可以看出:輸入中的回車符變?yōu)椤鋅0′附在最后;用puts函數(shù)輸出時遇到′\0′變?yōu)榛剀嚪麚Q行,因此有兩行“very”。在輸出第二個“very”并換行后又執(zhí)行putchar(′\n′),則又空出一行。當遇到fputs時,輸出“very”后不換行,則第二個“very”就在同一行輸出了。
【例9―4】將一個磁盤文件上的內(nèi)容加上行序號顯示在屏幕上,并復(fù)制到另一個磁盤文件中。#include<stdio.h>
#include<stdlib.h>
main(int
argc,char*argv[]){charbuff[256];
FILE*fp1,*fp2;
intline;
if(argc!=3){puts(″3parameters\n″);
exit(0);
}
if(((fp1=fopen(argv[1],″r″))=NULL||((fp2=fopen(argv[2],″w″))=NULL)) {printf(″Openfail\n″);
exit(0);
} line=1;
while(fgets(buff,256,fp1)!=NULL) {printf(″%3d:%s″,line++,buff); fputs(buff,fp2); }fclose(fp1);
fclose(fp2);
return0;}函數(shù)fgets從fp1文件中輸入一行字符送入buff緩沖區(qū)中,然后用printf函數(shù)語句把它的行號與buff中的字符串送到顯示器顯示,又用fputs函數(shù)把該行送入文件fp2中。這是在DOS命令提示符下進行的操作,所以在把程序編譯、連接后,生成.exe文件,設(shè)文件名為fcopy,則在執(zhí)行
c:\>fcopyfile1.txtfile2.txt
之后,file1中的內(nèi)容既在屏幕上顯示,又被復(fù)制到文件file2中。
3.文件數(shù)據(jù)塊的輸入/輸出函數(shù)fread和fwrite
fgetc和fputc函數(shù)一次只能讀寫一個字符,fgets和fputs函數(shù)一次只能讀寫不能確定字符個數(shù)的一串字符。但是,在程序的應(yīng)用中,我們常常需要能夠一次讀寫有一定字符長度的數(shù)據(jù),比如一個記錄等等,為此C語言又提供了兩個這樣的讀/寫函數(shù)即fread和fwrite函數(shù)。
1)fread函數(shù)
fread函數(shù)調(diào)用的一般格式為:
fread(buf,size,count,fp);其中buf是一個指針,指向輸入數(shù)據(jù)在內(nèi)存中的起始地址;size為要讀取的字節(jié)個數(shù);count為要讀取多少個size字節(jié)的數(shù)據(jù)項;fp為指向由fopen打開的文件的指針。功能:從fp指定的文件中讀取size*count個字節(jié)的數(shù)據(jù),并把它放入由buf指定的內(nèi)存中。當文件以二進制形式打開(即fp=fopen(″file1″,″rb″);)時,fread函數(shù)就可以用來讀取各種類型的數(shù)據(jù)信息。如:
fread(fbuf,sizeof(float),4,fp);則從fp指定的文件中讀出4個大小為size(float)的數(shù)據(jù)放入fbuf中,fbuf為一實型數(shù)組名,也是其第一個元素的地址。
fread函數(shù)的返回值:若讀取成功,則返回讀取的項數(shù)即count值;若讀取失敗,則返回-1。
2)fwrite函數(shù)
fwrite函數(shù)調(diào)用的格式為:
fwrite(buf,size,count,fp);其中,參數(shù)的個數(shù)和類型與fread函數(shù)完全一樣,只是它進行相反的操作。這里的buf是輸出數(shù)據(jù)在內(nèi)存中存放的地址。功能:把buf中大小為size*count個字節(jié)的數(shù)據(jù)寫入fp指定的文件中。如語句:
fwrite(ibuf,2,5,fp);是把整型數(shù)組中的5個整數(shù)寫入fp指定的文件中。返回值:若輸出成功,則返回寫入文件中的數(shù)據(jù)項數(shù);若輸出失敗,則返回-1。常常聯(lián)合使用fread和fwrite函數(shù)對二進制文件進行讀寫。
【例9―5】從鍵盤錄入n個學生的準考證號、姓名、總分,把這些數(shù)據(jù)保存到磁盤文件kaosheng.lst中,然后再從磁盤文件中讀出并在屏幕上顯示出來。#include<stdio.h>
#defineN500
structstudent{unsignedlongno;charname[15];
floatscore;}stud[N];
typede
fstructstudentSTU;
voidsave(void);voidload(void);
intm=0;main(){
inti,m;
printf(″Input
studentnumbern:1≤n≤N\n″);
scanf(″%d″,&m);
for(i=0;i<m;i++)
scanf(″%lu%s%f″,&stud[i].no,stud[i].name,&stud[i].score);
save(); load(); return0;}voidsave(void){FILE*fp;
inti;
if((fp=fopen(″A:\\kaosheng.lst″,″wb″)==NULL){
printf(″Openfail\n″); exit(0); }
for(i=0;i<m;i++)
if(fwrite(&stud[i],sizeof(STU),1,fp)!=1){
printf(″Filewriteerror!\n″); exit(0);
}
fclose(fp);}voidload(void){inti;
if((fp=fopen(″A:\\kaosheng.lst″,″rb″))=NULL) {printf(″Openfail\n″);exit(0);
}for(i=0;i<m;i++) {if(fread(&stud[i],sizeof(STU),1,fp)!=1)
{printf(″Filereaderror\n″); exit(0);
}
printf(″No:%lu\tName:%s\tscore:%f\n″,stud[i].no,
stud[i].name,stud[i].score);}
fclose(fp);}在save和load函數(shù)中都是用if語句的條件判斷,即利用fwrite和fread函數(shù)成功執(zhí)行后返回寫入和讀出的數(shù)據(jù)塊的項數(shù)的特點來完成輸入/輸出工作的,使程序顯得非常簡潔;另外使用typedef把一個長的結(jié)構(gòu)體類型名structs
tudent簡稱為STU,這樣在程序中簡化了書寫。
4.文件的格式化輸入/輸出函數(shù)fscanf和fprintf
這兩個函數(shù)的調(diào)用格式分別是:
fscanf(<文件指針>,<格式控制串>,<輸入列表>)
fprintf(<文件指針>,<格式控制串>,<輸出列表>)
它們的作用與scanf函數(shù)和printf函數(shù)幾乎一樣,差別只在于它們可以對任何文件進行輸入/輸出,而scanf和printf只對終端設(shè)備進行。因此使用fscanf和fprintf函數(shù)時應(yīng)該帶一個文件指針,如
fscanf(fp,″%d%f″,&i,&x);
表示從fp所指文件中讀入一個整數(shù)給i,一個浮點數(shù)給x(這樣做要非常小心,必須先要知道磁盤上的數(shù)據(jù)是如何存儲的)。
9.3.3文件的定位我們已經(jīng)知道,C語言中的文件是流式文件,處理文件的方式是順序處理。文件一打開,就有一個定位指針指向規(guī)定的地方,隨著讀寫的進行,定位指針自動向下移動。但在很多情況下需要改變這種順序讀寫的方法,即能任意指定讀寫位置,為此C語言又提供了相應(yīng)的函數(shù),主要有:返回文件定位指針當前位置的函數(shù)ftell()、改變文件定位指針當前位置的函數(shù)fseek()和重新把文件定位指針置于文件頭的函數(shù)rewind()。
1.ftell函數(shù)該函數(shù)的功能是返回文件定位指針的當前位置,即相對于文件頭的位移量(長整型),文件頭的位置定為0。函數(shù)的參數(shù)是文件指針。如果該函數(shù)運行不正常,則返回值為-1L,表示出錯。程序中可利用返回值來判斷函數(shù)調(diào)用是否出錯,如
i=ftell(fp);
if(i==-1L)printf(″ERROR\n″);
當文件剛打開時,ftell返回值為0L。
2.rewind函數(shù)該函數(shù)的功能是把文件定位指針重新拉回到文件開頭。這在對文件進行多遍操作時非常有用,即不需要反復(fù)進行文件關(guān)閉與打開操作,只需調(diào)用rewind函數(shù)即可。其調(diào)用格式為:
rewind(fp);表示把fp所指文件的定位指針拉回到文件頭,不管它現(xiàn)在處于什么位置。
3.fseek函數(shù)該函數(shù)的功能是把文件定位指針設(shè)置到需要的地方。該函數(shù)的調(diào)用格式為:
fseek(<文件指針>,<位移量>,<起始點>);其中,<位移量>是長整型,長整型的標志是整型數(shù)據(jù)后加字符“L”;位移量可正可負,正代表向后(尾),負代表向前(頭);<起始點>即位移的參照點,共有三個,可以用名字,也可用相應(yīng)的數(shù)字表示。具體情況如表9―2所示。表9―2起始點的表示例如:
fseek(fp,50L,0);/*定位于距文件頭50個字節(jié)處*/fseek(fp,-25L,1);/*定位于當前位置前25個字節(jié)處*/
fseek(fp,-10L,2);/*定位于文件尾前10個字節(jié)處*/
【例9―6】設(shè)文件stu.txt中存有40名學生的信息,學號從1到40編號。將學生的信息按學號的奇偶分為兩組,分別加以輸出。#include<stdio.h>
#defineN40
structstudent{intno;charname[15];
floatscore;}stud[N];
typedef
structstudentSTU;main(){FILE*fp;
inti;
if((fp=fopen(″a:\\stu.txt″,″rb″)==NULL){printf(″Openfail\n″);exit(0);}
printf(″Listoddno.students:\n″);
for(i=0;i<N;i++){fseek(fp,2*i*sizeof(STU),0);
if(fread(&stud[i],s
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 藥理麻醉藥試題及答案
- 衛(wèi)生部醫(yī)院藥事管理制度
- 醫(yī)院衛(wèi)生獎罰制度
- 衛(wèi)生部病人管理制度
- 肝移植術(shù)后AKI的CRRT酸堿方案
- 使用控件制作交互性課件
- 深度解析(2026)《SYT 6156-2017氣槍震源使用技術(shù)規(guī)范》
- 聯(lián)合用藥FIH試驗劑量遞推
- 職場健康管理:“治未病”的企業(yè)溝通策略
- 公安藍色培訓課件
- 2026年上半年眉山天府新區(qū)公開選調(diào)事業(yè)單位工作人員的參考題庫附答案
- 水產(chǎn)養(yǎng)殖技術(shù)手冊
- 2025年及未來5年市場數(shù)據(jù)中國吸塑、注塑行業(yè)發(fā)展前景預(yù)測及投資戰(zhàn)略數(shù)據(jù)分析研究報告
- 物流金融理論與實務(wù)課件
- 海內(nèi)外云廠商發(fā)展與現(xiàn)狀(三):資本開支壓力與海外云廠需求情況拆解-國信證券
- 2025年社區(qū)網(wǎng)格員招錄考試真題庫(含答案)
- GB/T 46510-2025玩具水基材料中游離甲醛的測定高效液相色譜法
- 溴化鋰清洗施工方案
- 第四方支付業(yè)務(wù)合規(guī)指引
- 手勢舞基本功課件
- 人教版七年級英語上冊全冊語法知識點梳理
評論
0/150
提交評論