版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、,文件操作系統(tǒng)管理數(shù)據(jù)的基本單位存儲在外存儲器上的數(shù)據(jù)的集合使用文件的目的程序與數(shù)據(jù)分離:數(shù)據(jù)文件的改動不引起程序的改動數(shù)據(jù)共享:不同程序可以訪問同一數(shù)據(jù)文件中的數(shù)據(jù)能長期保存程序運行的中間數(shù)據(jù)或結(jié)果數(shù)據(jù),第9章 文件操作,本章要求:,掌握C語言中文件的概念掌握打開文件的不同模式掌握使用各種操作函數(shù)對文件進(jìn)行讀寫的方法能編寫與文件有關(guān)的程序,本章難點: 掌握文件的各種操作函數(shù),能對文件進(jìn)行讀寫數(shù)據(jù)操作。,本章重點
2、: 掌握文件的各種操作函數(shù),能對文件進(jìn)行讀寫數(shù)據(jù)操作。,第9章 文件操作,9.1.1 文本文件與二進(jìn)制文件,C語言把文件看作一個字節(jié)序列,即由一連串的字節(jié)組成,稱為“流”,每一個字節(jié)都可以單獨讀取,每一個文件或者以文件結(jié)束標(biāo)志結(jié)束,或者在特定的字節(jié)號處結(jié)束。按數(shù)據(jù)的組織形式分類 1、文本文件又稱ASCII文件,每個字節(jié)對應(yīng)一個字符,用于存放該字符的ASCII碼,輸入輸出時對字符逐個處理。文本文件由文本行組成,每行中可
3、以有0個或多個字符,并以行終止符‘\n’結(jié)尾,文件結(jié)尾是文件結(jié)束標(biāo)志,該標(biāo)志后再沒有字符出現(xiàn)了。 2、二進(jìn)制文件數(shù)據(jù)按其在內(nèi)存中的存儲形式原樣存放,00100111 00010000,,內(nèi)存存儲形式,00100111 00010000,,二進(jìn)制形式,00110001 00110000 00110000 00110000 00110000,,,,,ASCII形式,,,文本文件特點: 速度慢、便于對
4、字符操作,二進(jìn)制文件特點: 速度快、便于存放中間結(jié)果,【例】整數(shù)10000,9.1.2 緩沖文件系統(tǒng),緩沖文件系統(tǒng):系統(tǒng)自動地為每一個正在使用的文件在內(nèi)存中開辟一個緩沖區(qū)。對輸入輸出進(jìn)行緩沖,可以大塊地轉(zhuǎn)移信息,而不再是一個個字節(jié)進(jìn)行操作。內(nèi)存緩沖區(qū)的大小,影響著操作外存的次數(shù)。內(nèi)存緩沖區(qū)越大,則操作外存的次數(shù)就少,執(zhí)行速度就快、效率高。,,9.1.3 文件類型指針,C語言的緩沖文件系統(tǒng)中,用文件類型指針來表示文
5、件。定義文件類型指針的一般形式:,FILE *指針變量名;,C編譯系統(tǒng)定義的一種結(jié)構(gòu)體類型,其中的成員用于存放有關(guān)文件的一些信息(文件名、文件狀態(tài)和文件當(dāng)前讀寫位置等),指針變量用于指向一個文件,實際上是用于存放文件緩沖區(qū)的首地址。,FILE結(jié)構(gòu)體是在頭文件中定義的,對文件操作的程序,在最前面都應(yīng)寫上文件包含命令: #include C語言通過文件指針變量對文件進(jìn)行打開、讀、寫及關(guān)閉操作。,FILE結(jié)構(gòu)體類型在頭文件stdio.h
6、中定義如下:typedef struct{short level;/*文件緩沖區(qū)占用程度*/unsigned flags; /*文件狀態(tài)標(biāo)志*/char fd;/*文件描述符*/unsigned char hold;/*若無緩沖區(qū)不讀取字符*/short bsize;/*文件緩沖區(qū)大小*/u
7、nsigned char *buffer;/*數(shù)據(jù)緩沖區(qū)的位置*/unsigned char *curp;/*指針當(dāng)前的位置*/unsigned istemp;/*臨時文件指示器*/short token;/*用于操作有效性檢查*/} FILE;/*文件類型符*/,9.1.3 文件類型指針,在編程時不必關(guān)心FILE結(jié)構(gòu)的具體細(xì)節(jié),只需在使用I/O函數(shù)時用這個文
8、件指針變量來指定所操作的文件。,9.1.3 文件類型指針,在C語言程序中使用文件,需要完成以下工作:1)聲明一個FILE類型的文件指針變量;2)打開文件:調(diào)用fopen函數(shù)將此文件指針變量和某一個實際的磁盤文件相聯(lián)系。要求指定文件名,并且說明對該文件是輸入操作還是輸出操作。3)讀寫文件:調(diào)用適當(dāng)?shù)奈募僮骱瘮?shù)完成必要的I/O操作。對輸入文件來說,函數(shù)從文件中將數(shù)據(jù)讀取至程序中;對輸出文件來說,函數(shù)將程序中的數(shù)據(jù)轉(zhuǎn)移到文件中
9、去。4)關(guān)閉文件:調(diào)用fclose函數(shù)表明文件操作結(jié)束,斷開文件指針與實際文件之間的聯(lián)系。,9.2 文件的打開與關(guān)閉,9.2.1 文件的打開,打開文件,實際上是建立文件的各種有關(guān)信息,并使文件指針指向該文件;緩沖文件系統(tǒng)借助文件指針來對文件進(jìn)行管理和訪問,既可以讀寫字符、字符串、格式化數(shù)據(jù),也可以讀寫二進(jìn)制數(shù)據(jù)。,“文件名”和“文件打開模式”都是字符串常量或字符數(shù)組。,文件指針名=fopen("文件名",&qu
10、ot;文件打開模式"),需要打開的文件的名字,確定文件的數(shù)據(jù)操作方式,打開文件使用函數(shù)fopen其調(diào)用的一般形式為:,舉 例,FILE *fp; fp=fopen("source.txt","r");,作用:以讀的方式(“r”模式即表示讀“read”)打開當(dāng)前目錄下文件名為source.txt的文件。如果打開文件成功,則返回一個指向source.txt文件信息區(qū)的起始地址的指針
11、,并賦值給fp,即fp指向了文件source.txt。其后所有對該文件的操作都必須通過fp指針來實現(xiàn)。如果文件打開失敗,則返回一個空指針NULL,賦值給fp。 說明:文件名可以包含路徑和文件名兩部分。寫路徑時,因為轉(zhuǎn)義字符以反斜杠開頭,所以“\\”才是表示一個反斜杠?!纠咳袈窂胶臀募麨椋骸癱:\tc\source.txt”,則應(yīng)寫成“c:\\tc\\source.txt”。,9.2.1 文件的打開,文件的打開模式,9.2.
12、1 文件的打開----模式說明,1)“r”模式:只能用于輸入(讀操作),且只能打開一個已經(jīng)存在的文件。 2)“w”模式:只能用于輸出(寫操作)。如果指定的文件不存在,則新建一個文件;如果文件存在,則把原來的文件刪除,再重新建立一個空白的文件。 3)“a”模式:用于追加操作。如果指定的文件不存在,則新建該文件;如果文件存在,保留該文件原有的數(shù)據(jù),在原文件的末尾添加新的數(shù)據(jù)。 4)打開方式帶上“b”表示是對二進(jìn)制
13、文件進(jìn)行操作。帶上“+”表示既可以讀,又可以寫。而對待文件存在與否的不同處理則按照“r”、“w”、“a”各自的規(guī)定。5)如果在打開文件時發(fā)生錯誤,即打開失敗,fopen返回一個空指針NULL。,文件打開可能出現(xiàn)的錯誤有:試圖以“讀”模式(帶“r”的方式)打開一個并不存在的文件;試圖以“寫”方式(帶“w”或“a”的方式、“r+”或“rb+”方式)打開被設(shè)置為“只讀”屬性的文件。新建一個文件,而磁盤上沒有足夠的剩余空間或磁盤被寫保護(hù)
14、。用不正確的模式打開一個文件可能會破壞文件的內(nèi)容。 為避免因上述原因的出錯,常用以下的方法來打開一個文件:,9.2.1 文件的打開----模式說明,if((fp=fopen("source.txt","r"))==NULL) { printf("This file could not be opened !\n"); exit(0) /*
15、返回操作系統(tǒng)*/ } else { ┇ /*此處編寫對文件讀/寫的代碼*/ },#include ,9.2 文件的打開與關(guān)閉,9.2.2 文件的關(guān)閉,【例】fclose(fp)關(guān)閉由指針fp指定的文件,同時根據(jù)需要刷新緩沖區(qū)。如果文件成功關(guān)閉,fclose函數(shù)將返回值0,否則返回EOF。,fclose(文件指針變量);,對文件的操作完成后,應(yīng)確保關(guān)閉程序中打開的文件,以避免文件的數(shù)據(jù)丟失。 關(guān)閉
16、文件指斷開指針與文件之間的聯(lián)系,也就禁止再對該文件進(jìn)行操作。磁盤已滿、磁盤被移走或者出現(xiàn)I/O錯誤等都會導(dǎo)致fclose函數(shù)執(zhí)行失敗。,9.2 文件的打開與關(guān)閉,不關(guān)閉文件可能會丟失數(shù)據(jù),9.3 文件的讀寫,使用fopen成功打開文件后,都會有屬于該文件的一個文件讀寫位置指針,表示文件內(nèi)部即將要讀寫的位置。文件指針和文件內(nèi)部的讀寫位置指針是不同的,9.3.1 文件讀寫函數(shù)概述,,9.3 文件的讀寫,文件指針和文件內(nèi)部的讀寫位置指針
17、是不同的文件指針指向整個文件,在程序中定義,只要不重新賦值,文件指針的值不變。文件內(nèi)部的讀寫位置指針用于指示文件內(nèi)部的當(dāng)前讀寫位置,每讀寫一次,該指針均自動向后移動,指向下一個讀寫單元。它不需在程序中定義,由系統(tǒng)自動設(shè)置。 以“r”或“w”方式打開文件后,該文件讀寫位置指針初始值指向文件開頭;以“a”方式打開文件后,該文件讀寫位置指針初始值指向文件末尾。,9.3 文件的讀寫,對文件進(jìn)行讀寫操作時,需要判斷當(dāng)前讀寫位置,如果文件讀
18、操作到最后,再進(jìn)行讀寫操作就會出錯。為了避免出錯,C提供了下面的方式判斷文件是否讀完1、對于文本文件,結(jié)束標(biāo)記是EOF(即-1,在stdio.h中定義),可以通過讀取的字符是不是結(jié)束標(biāo)記來判斷文本文件是否讀完;2、對于二進(jìn)制文件,沒有EOF的結(jié)束標(biāo)志,只能使用系統(tǒng)提供的feof函數(shù)來判斷;其中,fp是文件指針變量,如果文件讀取結(jié)束則返回非0值,沒結(jié)束返回0值。3、文本文件可使用feof函數(shù)按上面形式來判斷是否讀取結(jié)束。
19、,while( !feof(fp)) { ┇ /*此處寫入讀操作語句*/ },使用格式是: feof(fp),9.3 文件的讀寫,9.3.2 字符讀寫函數(shù),(1)字符讀函數(shù)fgetc( )功能:從指定的文件中讀一個字符;函數(shù)調(diào)用的一般形式: 字符變量=fgetc(文件指針變量);【例】 ch=fgetc(fp1); /*從fp1指向的文件中讀取一個字符并送入變
20、量ch中*/說明:在fgetc函數(shù)調(diào)用中,讀取的文件必須是以讀或讀寫方式打開的讀取成功返回文件當(dāng)前位置的一個字符;讀錯誤時返回EOF。,,9.3 文件的讀寫,9.3.2 字符讀寫函數(shù),(2)字符寫函數(shù)fputc( )功能:將一個字符寫入到指定文件中;函數(shù)調(diào)用的一般形式: fputc(字符變量,文件指針變量);【例】 fputc(ch,fp2); /* 將字符變量ch中的字符寫入到fp2所指的文件中 */說明
21、:fputc函數(shù)也有返回值若寫操作成功,則返回向文件所寫的字符;否則返回EOF,表示寫操作失敗。,,例 9-1 用依次讀取字符的方式,將source.txt文件的內(nèi)容復(fù)制到destination.txt文件中。,9.3 文件的讀寫,void main(){ FILE *fp1,*fp2; char ch; if((fp1=fopen("C:\\source.txt","r&q
22、uot;))==NULL) { printf("File could not be opened!\n"); exit(0); } if((fp2=fopen("C:\\destination.txt","w"))==NULL) { printf("F
23、ile could not be opened!\n"); exit(0); } while((ch=fgetc(fp1))!=EOF) fputc(ch,fp2); fclose(fp1); fclose(fp2);},9.3.3 字符串讀寫函數(shù),(1)字符串讀函數(shù)fgets( )功能:從指定的文件中讀取一個字符串到程序中的字符數(shù)組
24、函數(shù)調(diào)用的一般形式: 參數(shù)n是一個正整數(shù),表示從文件中讀出的字符串不超過n-1個字符。因為要在讀入的最后一個字符后加上字符串結(jié)束標(biāo)志'\0'。說明:fgets函數(shù)從文件中讀取字符直到遇見回車符或EOF為止,或直到讀入了所限定的字符數(shù)(至多n-1個字符)為止。函數(shù)讀成功返回字符數(shù)組首地址;失敗返回空指針NULL。,9.3 文件的讀寫,fgets(字符數(shù)組名,n ,文件指針);,9.3.2 字符讀寫函
25、數(shù),(2)字符串寫函數(shù)fputs( )功能:將一個字符串寫入到指定文件中函數(shù)調(diào)用的一般形式: 字符串可以是字符串常量,也可以是字符數(shù)組名,或字符指針變量?!纠縞har *ch="You Are Good!" fputs(ch,fp2); /* 將字符指針ch指向的字符串寫入到文件fp2中 */說明:若函數(shù)調(diào)用fputs返回值為EOF時,表明寫操作失
26、敗。,9.3 文件的讀寫,fputs(字符串,文件指針),例9-2 修改例9-1程序,用讀取字符串的方式,將source.txt文件的內(nèi)容復(fù)制到destination.txt文件中。,9.3 文件的讀寫,void main(){ FILE *fp1,*fp2; char ch[80]; if((fp1=fopen("C:\\source.txt","r"))==N
27、ULL) { printf("File could not be opened!\n"); exit(0); } if((fp2=fopen("C:\\destination.txt","w"))==NULL) { printf("File cou
28、ld not be opened!\n"); exit(0); } while(!feof(fp1)) { fgets(ch,81,fp1); fputs(ch,fp2); } fclose(fp1); fclose(fp2); },9.3 文件的讀寫,字符讀寫函數(shù): fgetc()和fpu
29、tc()字符串讀寫函數(shù):fgets()和fputs()格式讀寫函數(shù): fscanf()和fprintf()數(shù)據(jù)塊讀寫函數(shù):fread()和fwrite(),9.3.4 格式讀寫函數(shù),(1)格式化讀函數(shù)fscanf功能:從指定的文件中按照一定的格式讀取數(shù)據(jù)到程序中fscanf與scanf功能相似,區(qū)別在于fscanf的讀取對象是磁盤文件,scanf的讀取對象是鍵盤。函數(shù)調(diào)用的一般形式:其中,格式字符串和輸入表列和
30、scanf函數(shù)相似。【例】fscanf(fp,"%5d",&a[i]);說明:函數(shù)的返回值若為EOF,表明格式化讀錯誤;否則讀數(shù)據(jù)成功。,9.3 文件的讀寫,fscanf(文件指針,"格式字符串",輸入表列);,(2)格式化寫函數(shù)fprintf功能:把格式化的數(shù)據(jù)寫到指定文件中fprintf與printf功能相似,區(qū)別在于fprintf是向文件中輸出,而printf是向屏幕輸出。
31、函數(shù)調(diào)用的一般形式: 其中,格式控制字符串和輸出項列表和printf函數(shù)相似。【例】 fprintf(fp,"%5d",a[i]);說明:函數(shù)的返回值為實際寫入文件中的字符個數(shù)(字節(jié)數(shù));若寫錯誤,則返回一個負(fù)數(shù)。,9.3 文件的讀寫,9.3.4 格式讀寫函數(shù),fprintf(文件指針,"格式控制字符串",輸出項列表);,例9-3 隨機(jī)產(chǎn)生20個[10,99]之間的整數(shù),以每
32、行5個數(shù)據(jù)輸出到文本文件c:\data.txt中,要求每個數(shù)據(jù)占5個寬度,并且數(shù)據(jù)之間用逗號分隔。然后將其讀出按升序排序后,按同樣格式追加寫在原文件后,與原數(shù)據(jù)之間空出2行。編程分析:采用模塊化程序設(shè)計將產(chǎn)生數(shù)據(jù)、將數(shù)據(jù)輸出到文件、從文件中讀取數(shù)據(jù),排序和追加數(shù)據(jù)到文件分別寫成GetData( )、PutDataToFile( )、GetDataFormFile( )和sort( )、AppendDataToFile( )函數(shù),9
33、.3 文件的讀寫,void main(){ int a[20],i; GetData(a,20); PutDataToFile(a,20); /*調(diào)用scandata()函數(shù)將數(shù)據(jù)讀入到數(shù)組a中*/ GetDataFormFile(a,20); sort(a,20); /*調(diào)用sort()函數(shù)將數(shù)組a的數(shù)據(jù)排序*/ /*調(diào)
34、用AppedDataToFile( ) 函數(shù)將排序后的數(shù)組a的數(shù)據(jù)寫入到文件中*/ AppendDataToFile(a,20);}void GetData(int a[],int n){ int i; srand(time(NULL)); /* 初始化隨機(jī)種子數(shù) */ for(i=0;i<n;i++) a[i]=(rand()%90)
35、+10; /* 產(chǎn)生[10,99]的隨機(jī)整數(shù) */},9.3 文件的讀寫,void PutDataToFile(int a[],int n){ int i; OpenFile("c:\\data.txt","w"); for(i=0;i<n;i++) { if(i%5==0) fpri
36、ntf(fp,"%5d",a[i]); else fprintf(fp,",%5d",a[i]); if((i+1)%5==0) fprintf(fp,"\n"); } fclose(fp);}void GetDataFormFile(int a[],int n)/*
37、 從文件讀數(shù)據(jù)函數(shù) */{ int i; OpenFile("c:\\data.txt","r"); for(i=0;i<n;i++) { if(i%5==0) fscanf(fp,"%5d",&a[i]); /* 每1行的第1個數(shù)據(jù)前不用逗號 */
38、 else fscanf(fp,",%5d",&a[i]); } fclose(fp);},9.3 文件的讀寫,void sort(int a[],int n){ int i,j,k,t; for(i=0;ia[j])k=j; t=a[i]; a[i]=a[k]; a[k]=t; }
39、}void OpenFile(char *file,char *pr) { if((fp=fopen(file,pr))==NULL)/* 打開文件失敗 */ { printf("Cannot open file,stike any key to exit!"); exit(0);/* 退出程序 */ } },9.3 文件的讀寫,v
40、oid AppendDataToFile(int a[],int n) /*追加數(shù)據(jù)函數(shù) */{ int i; OpenFile("c:\\data.txt","a"); /* 打開文件失敗 */ fprintf(fp,"\n\n"); /* 輸出2個空行 */ for(i=0;i<n;i++)
41、{ if(i%5==0) fprintf(fp,"%5d",a[i]); else fprintf(fp,",%5d",a[i]); if((i+1)%5==0) fprintf(fp,"\n"); } fcl
42、ose(fp);},9.3 文件的讀寫,#include #define STUNUM 5 /*代表學(xué)生人數(shù)*/#define COURSENUM 3 /*代表課程門數(shù)*/struct student{ int sno; /*學(xué)號*/ char sname[10]; /*學(xué)生姓名*/ int score[COURSENUM]; /*每個學(xué)生的三門課
43、成績*/}stu1[STUNUM],stu2[STUNUM];,例9-4 從鍵盤輸入5個學(xué)生的學(xué)號、姓名和成績,將學(xué)生數(shù)據(jù)寫入文件,然后再從文件中將這些信息讀出顯示在屏幕上。,9.3 文件的讀寫,void main(){ FILE *fp; int i,j; if((fp=fopen("c:\\stu.txt","w+"))==NULL) {
44、 printf("File could not be opened!\n"); exit(0); } printf("input data:\n"); for(i=0;i<STUNUM;i++)/*從鍵盤輸入學(xué)生數(shù)據(jù)*/ { scanf("%d",&stu1[i].sno);
45、 scanf("%s ",stu1[i].sname); for(j=0;j<COURSENUM;j++) scanf("%d",&stu1[i].score[j]); },9.3 文件的讀寫,for(i=0;i<STUNUM;i++)/*學(xué)生數(shù)據(jù)寫入文件中*/{ fprint
46、f(fp,"%d,",stu1[i].sno); fprintf(fp,"%s,",stu1[i].sname); for(j=0;j<COURSENUM;j++) fprintf(fp,"%d,",stu1[i].score[j]); } rewind(fp);/*文件的位置指針移動到文件開始處*/ fo
47、r(i=0;i<STUNUM;i++) /*將文件中學(xué)生數(shù)據(jù)讀入程序中*/ { fscanf(fp,"%d,",&stu2[i].sno); fscanf(fp,"%s,",stu2[i].sname); for(j=0;j<COURSENUM;j++) fscanf(fp,"%d,"
48、;,&stu2[i].score[j]); },9.3 文件的讀寫,printf("\nsno\tsname\t\tscores\n"); for(i=0;i<STUNUM;i++) /*將讀出的數(shù)據(jù)顯示在屏幕上*/ { printf("%d\t",stu2[i].sno); printf("%s\t",stu2[i].
49、sname); for(j=0;j<COURSENUM;j++) printf("%d\t",stu2[i].score[j]); printf("\n"); } fclose(fp);},9.3 文件的讀寫,9.3.5 數(shù)據(jù)塊讀寫函數(shù),(1)讀取數(shù)據(jù)塊函數(shù)fread功能:從指定文件中讀取若干個數(shù)據(jù)塊到程序中
50、函數(shù)調(diào)用的一般形式為:參數(shù)buffer是一個指針,表示存放輸入數(shù)據(jù)的內(nèi)存存儲地址;參數(shù)size表示一個數(shù)據(jù)塊的字節(jié)數(shù);參數(shù)count表示要讀寫的數(shù)據(jù)塊塊數(shù)。,9.3 文件的讀寫,fread(buffer,size,count,fp);,9.3.5 數(shù)據(jù)塊讀寫函數(shù),(2)寫數(shù)據(jù)塊函數(shù)fwrite功能:將若干個數(shù)據(jù)塊寫入到指定的文件中函數(shù)調(diào)用的一般形式為:參數(shù)buffer是一個指針,表示存放輸出數(shù)據(jù)的內(nèi)存存儲地址;
51、參數(shù)size表示一個數(shù)據(jù)塊的字節(jié)數(shù);參數(shù)count表示要讀寫的數(shù)據(jù)塊塊數(shù)。,9.3 文件的讀寫,fwrite(buffer,size,count,fp);,#include #define STUNUM 5 /*代表學(xué)生人數(shù)*/#define COURSENUM 3 /*代表課程門數(shù)*/struct student{ int sno;/*學(xué)號*/ char sname[10];/*學(xué)生姓名
52、*/ int score[COURSENUM];/*每個學(xué)生的3門課成績*/}stu1[STUNUM],stu2[STUNUM];,例9-5 改寫例9-4使用數(shù)據(jù)塊讀寫函數(shù)從鍵盤輸入5個學(xué)生的學(xué)號、姓名和成績,將學(xué)生數(shù)據(jù)寫入文件,然后再從文件中將這些信息讀出顯示在屏幕上。,9.3 文件的讀寫,void main(){ FILE *fp; int i,j; if((fp=fopen("c:\\stu.dat&
53、quot;,"wb+"))==NULL) /*二進(jìn)制模式打開文件讀和寫*/ {printf("File could not be opened!\n"); exit(0); } printf("input data:\n"); for(i=0;i<STUNUM;i++)/*從鍵盤輸入學(xué)生數(shù)據(jù)*/ { scanf("%d,&
54、quot;,&stu1[i].sno); scanf("%s ",stu1[i].sname); for(j=0;j<COURSENUM;j++) scanf("%d,",&stu1[i].score[j]); },9.3 文件的讀寫,fwrite(stu1,sizeof(struct student), STUNUM,fp)
55、; /*學(xué)生數(shù)據(jù)寫入文件中*/ rewind(fp); /*文件的位置指針移動到文件開始處*/ fread(stu2,sizeof(struct student), STUNUM,fp); /*將文件中數(shù)據(jù)讀入程序中*/ printf("\nsno \t\t\tsname\tscores \n"); for(i=0;i<STUNUM;i+
56、+) /*將讀出的數(shù)據(jù)顯示在屏幕上*/ { printf("%d\t",stu2[i].sno); printf("%s\t",stu2[i].sname); for(j=0;j<COURSENUM;j++) printf("%d\t",stu2[i].score[j]); printf("\n"); } fclos
57、e(fp); },9.3 文件的讀寫,9.3.6 隨機(jī)讀寫文件,前面的文件讀寫函數(shù)都是以順序的方式操作的,如果用戶希望直接讀取文件中某一部分的信息,必須從文件頭開始讀,直到要求的文件讀寫位置再進(jìn)行操作,這顯然不方便。 為了解決這個問題,可以移動文件內(nèi)部的位置指針到需要讀寫的位置,再進(jìn)行讀寫,這種讀寫方式稱為隨機(jī)讀寫。 隨機(jī)讀寫最常用于二進(jìn)制文件。 實現(xiàn)隨機(jī)讀寫的關(guān)鍵是按要求移動位置指針,這稱為文件的定位。 C語言提供了一組文
58、件的隨機(jī)讀寫函數(shù),可以將文件讀寫位置指針定位在所要求讀寫的地方,從而實現(xiàn)隨機(jī)讀寫。,9.3 文件的讀寫,函數(shù)原型:int fseek(FILE *stream, long offset, int fromwhere)功能:將文件的讀寫位置指針設(shè)置到特定的位置返回值:成功,返回0;失敗,返回非0值,位移量(以起始點為基點,移動的字節(jié)數(shù))>0 向后移動; <0 向前移動; =0保持不動,起始點文件開始
59、 SEEK_SET 0文件當(dāng)前位置 SEEK_CUR 1文件末尾 SEEK_END 2,例 fseek(fp,100L,0); fseek(fp,50L,1); fseek(fp,-10L,2);,fseek函數(shù),9.3 文件的讀寫,ftell函數(shù):long ftell(FILE *stream);返回文件讀寫位置指針的當(dāng)前值,這個值是從文件頭開始算起到文件指針位
60、置的字節(jié)數(shù),返回的數(shù)為長整型數(shù);若返回-1,表明出現(xiàn)錯誤。 rewind函數(shù):int rewind(FILE *stream);用于將文件內(nèi)部的讀寫位置指針移動到文件的開始處;成功時返回0;否則,返回非0值。,9.3 文件的讀寫,#include #define STUNUM 5/*代表學(xué)生人數(shù)*/#define COURSENUM 3/*代表課程門數(shù)*/struct student{ int
61、sno;/*學(xué)號*/ char sname[10];/*學(xué)生姓名*/ int score[COURSENUM];/*每個學(xué)生的三門課成績*/ }stu; void main(){ FILE *fp; int i; if((fp=fopen("c:\\stu.dat","rb"))==NULL)
62、 { printf("File could not be opened!\n"); exit(0); },例9-6 從例9-5所建立的文件c:\stu.dat中讀取第2個學(xué)生的所有信息并顯示在屏幕上。,9.3 文件的讀寫,fseek(fp,1L*sizeof(struct student),SEEK_SET); /* 文件位置指針移動
63、到第一個學(xué)生數(shù)據(jù)之后 */ fread(&stu,sizeof(struct student),1,fp); /*將文件中該學(xué)生數(shù)據(jù)讀入變量中*/ printf("\nsno\tscores\t\t\tsname\n"); /*將讀出的學(xué)生數(shù)據(jù)顯示在屏幕上*/ printf("%d\t",stu.sn
64、o); printf("%s\n",stu.sname); for(i=0;i<COURSENUM;i++) printf("%d\t",stu.score[i]); fclose(fp);},9.3 文件的讀寫,本章結(jié)束,9.4 應(yīng)用舉例,9.4.1 文件的加密和解密,例9-8 設(shè)計
65、一個對指定文件進(jìn)行加密和解密的程序,密碼和文件名由用戶輸入?!炯用芊椒ā恳远M(jìn)制打開文件,將密碼中每個字符的ASCII碼值與文件的每個字節(jié)進(jìn)行異或運算,然后寫回原文件原位置即可。這種加密方法是可逆的,即對明文進(jìn)行加密得到密文,用相同的密碼對密文進(jìn)行加密就得到明文。此方法適合各種類型的文件加密解密。 下面用兩種方法實現(xiàn)對文件的加密和解密。,9.4 應(yīng)用舉例,方法一:程序運行后,用戶在提示下輸入文件名和密碼。編輯分析:由于涉及到文件
66、的讀和寫,采用逐個字節(jié)從原文件中讀出,加密后寫入一個新建的臨時文件,最后,刪除原文件,把臨時文件改名為原文件名,完成操作。,#include #include char encrypt(char f, char c) /*字符加密函數(shù)*/{ return f ^ c; /*返回兩字符ASCII碼按位做異或運算的結(jié)果*/},void main(){ FILE *fp, *fp1;
67、 char fn[40], *p=fn, ps[10], *s=ps; char ch; char *tm= "C:\\temp.tmp";//臨時文件名 printf("Input the path and filename:"); gets(p);//輸入文件名 *tm=*p; //確保臨時
68、文件和要加密的文件在同一盤內(nèi) // 判斷文件是否能打開,臨時文件是否能建立 if((fp=fopen(p,"rb"))==NULL||(fp1=fopen(tm,"wb"))==NULL) { printf("Cannot open file strike any key exit!"); e
69、xit(0);// 退出 } printf("Input the password:"); gets(s); // 輸入密碼,9.4 應(yīng)用舉例,ch=fgetc(fp); while(!feof(fp))//當(dāng)原文件沒讀完時 { s=ps; //從密碼的第一個字符開始處理 while(*s
70、!= '\0') ch=encrypt(ch, *s++); //調(diào)用函數(shù)加密,讓s指向下一個密碼字符 fputc(ch, fp1); // 把加密后的字節(jié)寫入臨時文件 ch=fgetc(fp); // 讀入一個字節(jié) } fcl
71、ose(fp); fclose(fp1); remove(p); // 刪除原文件 rename(tm, p); // 把臨時文件改名為原文件名},9.4 應(yīng)用舉例,方法二:將要加密的文件和密碼,通過命令行參數(shù)傳遞給程序,并且加密解密過程對文件的讀寫采有隨機(jī)讀寫,不建立臨時文件,程序代碼如下:,#include #include char encrypt(char f
72、,char c)//字符加密函數(shù) { return f ^ c;//返回兩字符ASCII碼按位做異或運算的結(jié)果 },9.4 應(yīng)用舉例,void main(int argc,char *argv[])//main函數(shù)帶兩個參數(shù){ FILE *fp; char *s,ch; if(argc!=3)//如果輸入的命令行參數(shù)數(shù)目不正確 { printf("Parameter Erro
73、r! strike any key exit!"); exit(0);//退出 } if((fp=fopen(argv[1],"rb+"))==NULL) { printf("Cannot open file strike any key exit!"); exit(0);//退出 }
溫馨提示
- 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. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
評論
0/150
提交評論