C語言入門經(jīng)典(第四版)12-處理文件.ppt_第1頁(yè)
C語言入門經(jīng)典(第四版)12-處理文件.ppt_第2頁(yè)
C語言入門經(jīng)典(第四版)12-處理文件.ppt_第3頁(yè)
C語言入門經(jīng)典(第四版)12-處理文件.ppt_第4頁(yè)
C語言入門經(jīng)典(第四版)12-處理文件.ppt_第5頁(yè)
已閱讀5頁(yè),還剩38頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、第12章 處理文件,如果計(jì)算機(jī)只能處理存儲(chǔ)在主內(nèi)存中的數(shù)據(jù),則應(yīng)用程序的適用范圍和多樣性就會(huì)受到相當(dāng)大的限制。事實(shí)上,所有重要的商業(yè)應(yīng)用程序所需的數(shù)據(jù)量遠(yuǎn)遠(yuǎn)大于主內(nèi)存所能提供的數(shù)據(jù)量,常常需要具備處理外部設(shè)備(例如固定磁盤)所存儲(chǔ)的數(shù)據(jù)的能力。本章將了解如何處理外部設(shè)備上的文件數(shù)據(jù) 。,12.1 文件的概念,在前面的所有例子中,用戶在執(zhí)行程序時(shí)輸入的任何數(shù)據(jù),在程序結(jié)束后都會(huì)消失。此時(shí)如果用戶要用相同的數(shù)據(jù)執(zhí)行程序,就必須重新輸入一遍。這種方式不僅不方便,還使編程任務(wù)無法完成 。 文件中的位置 文件流,12.1.1 文件中的位置,文件有開頭和結(jié)尾,還有一個(gè)當(dāng)前位置,通常定義為從文件頭到當(dāng)前位置

2、有多少個(gè)字節(jié)數(shù),如圖12-1所示。當(dāng)前位置就是發(fā)生文件操作(讀寫文件的動(dòng)作)的地方。當(dāng)前位置可以移動(dòng)到文件的其他地方去。新的當(dāng)前位置可以指定為距離文件開頭的偏移量,或在某些情況下,指定為從前一個(gè)當(dāng)前位置算起的正或負(fù)偏移量 。,12.1.2 文件流,C庫(kù)提供了讀寫數(shù)據(jù)流的函數(shù)。流是外部數(shù)據(jù)源或數(shù)據(jù)目的地的抽象表示,所以鍵盤、顯示器上的命令行和磁盤文件都是流。因此,可以使用輸入輸出函數(shù)讀寫映射為流的任意外部設(shè)備 。,12. 2 文件訪問,磁盤上的每個(gè)文件都有一個(gè)名稱,文件命名規(guī)則由操作系統(tǒng)確定。如果一個(gè)處理文件的程序只能處理特殊名字的文件,就不是很方便,需要為每個(gè)要處理的文件編寫不同的程序。因此,

3、在C語言中處理文件時(shí),程序通過文件指針來引用文件。文件指針是一個(gè)抽象指針,關(guān)聯(lián)到一個(gè)特定的文件上,所以程序可以在不同的情況下處理不同的文件。文件指針指向表示流的結(jié)構(gòu)。本章的示例使用微軟的Windows文件名。如果使用其他操作系統(tǒng)(例如UNIX)就需要適當(dāng)?shù)卣{(diào)整文件的名稱 。 打開文件 文件重命名 關(guān)閉文件 刪除文件,12. 2.1 打開文件,將內(nèi)部文件指針變量關(guān)聯(lián)到一個(gè)特定的外部文件名稱上的過程稱為打開文件。調(diào)用標(biāo)準(zhǔn)庫(kù)函數(shù)fopen()就可以打開文件,該函數(shù)返回特定外部文件的文件指針。fopen()函數(shù)在中定義,它的原型如下: FILE *fopen(char *name, char* mod

4、e);,12. 2.2 文件重命名,在許多情況下都需要對(duì)文件進(jìn)行重命名。例如更新文件的內(nèi)容,創(chuàng)建一個(gè)新的、更新過的文件。這需要在創(chuàng)建新的文件后,給它指定一個(gè)臨時(shí)的文件名,然后刪除舊文件,再將這個(gè)臨時(shí)的文件名更改成被刪掉的文件名。文件重命名非常簡(jiǎn)單,只需使用rename()函數(shù),它的原型如下: int rename(const char *oldname, const char *newname);,12. 2.3 關(guān)閉文件,使用完文件后,需告訴操作系統(tǒng)釋放文件指針,這稱為關(guān)閉文件。這個(gè)動(dòng)作通過調(diào)用函數(shù)fclose()來完成。這個(gè)函數(shù)將文件指針作為變?cè)?,返回int類型的值。如果成功關(guān)閉文件,就返

5、回0,否則返回EOF。函數(shù)fclose()的使用方式如下: fclose(pfile); /* Close the file associated with pfile */,12. 2.4 刪除文件,現(xiàn)在可以在代碼中創(chuàng)建文件,有時(shí)也要編程刪除文件。此時(shí)可以使用在中聲明的函數(shù)remove(),其用法如下: remove(pfile.txt); 這行語句會(huì)從當(dāng)前目錄中刪除pfile.txt文件。在調(diào)用函數(shù)remove()刪除文件時(shí),文件不應(yīng)是打開的,否則,調(diào)用函數(shù)remove()的動(dòng)作取決于具體的C實(shí)現(xiàn)方式,請(qǐng)參閱庫(kù)文檔說明。 文件的任何動(dòng)作都需要檢查兩次,尤其是刪除文件的動(dòng)作 。,12.3 寫

6、入文本文件,打開一個(gè)文件以用于寫入數(shù)據(jù)后,就可以在程序的任何地方給它寫入數(shù)據(jù),只要可以訪問fopen()為文件設(shè)置的文件指針即可。如果要在包含多個(gè)函數(shù)的任意位置訪問文件,就需要確保文件指針有全局作用域,或可以作為變?cè)獋魉徒o訪問文件的函數(shù) 。,12.4 讀取文本文件,fgetc()函數(shù)與fputc()函數(shù)互補(bǔ),fgetc()從打開的文本文件中讀取一個(gè)字符。它將文件指針作為唯一的變?cè)?,如果讀取操作成功,就把讀取的字符返回為int類型;否則,返回EOF。fgetc()函數(shù)的一般用法如下面的語句所示: mchar = fgetc(pfile); /* Reads a character into mc

7、har */,12.5 將字符串寫入文本文件,puts()函數(shù)將字符串寫入stdout,而函數(shù)fputs()會(huì)將字符串寫入文本文件。它的原型如下: int fputs(char *pstr, FILE *pfile); 第一個(gè)變?cè)且獙懭胛募淖址羔?,第二個(gè)變?cè)俏募羔?。這個(gè)函數(shù)的動(dòng)作有點(diǎn)古怪,它會(huì)將字符串寫入文件,直到碰到0字符為止,但是0不會(huì)寫入文件。用fputs()寫入文件的不定長(zhǎng)的字符串,可以用fgets()將它讀取出來。這是因?yàn)樗且粋€(gè)字符寫入操作,不是二進(jìn)制寫入操作,所以它希望寫入的一行文本以換行符結(jié)束。這個(gè)函數(shù)不需要換行符,但是讀取文件(使用互補(bǔ)函數(shù)fgets()時(shí),換行符

8、會(huì)非常有用。,12.6 從文本文件中讀入字符串,fputs()的互補(bǔ)函數(shù)是fgets(),它可以從文本文件中讀入一個(gè)字符串。其函數(shù)原型如下: char *fgets(char *pstr, int nchars, FILE *pfile); fgets()有3個(gè)參數(shù)。它會(huì)從pfile所指向的文件將字符串讀入pstr所指向的內(nèi)存。 該函數(shù)會(huì)一直從文件中讀取字符串,直到讀到了n字符或讀入nchars1個(gè)字符為止 。,12.7 格式化文件的輸入輸出,將字符及字符串寫入文件比較順利,但是在程序中一般有許多其他的數(shù)據(jù)類型。例如,要將數(shù)值數(shù)據(jù)寫入文件,就需要更多的操作;要使文件中的內(nèi)容能讓人看得懂,還需要

9、數(shù)值數(shù)據(jù)的字符表示。而格式化文件的輸入輸出函數(shù)提供了這樣的機(jī)制 。 格式化文件輸出 格式化文件輸入,12.7.1 格式化文件的輸出,在第10章討論標(biāo)準(zhǔn)流時(shí),就遇到過格式化文件輸出的函數(shù)。它和printf()語句相同,但有一個(gè)額外的參數(shù),名稱也稍有不同。它的用法如下: fprintf(pfile, %12d112d%14f, num1, num2, fnum1); 可以看到,這個(gè)函數(shù)名稱比printf()多了一個(gè)f(文件),第一個(gè)變?cè)侵付ㄝ敵瞿康牡氐奈募羔?。顯然,文件指針需要通過調(diào)用fopen()來設(shè)定。其余的變?cè)蚿rintf()相同 。,12.7.2 格式化文件的輸入,使用fscanf(

10、)函數(shù)可以得到格式化文件輸入。例如,從文件pfile讀入3個(gè)變量值,可以使用如下語句: fscanf(pfile, %12d%12d%14f, 這個(gè)函數(shù)的操作和scanf()對(duì)stdin的操作完全相同,只是要從第一個(gè)變?cè)付ǖ奈募械玫捷斎?。scanf()函數(shù)的使用規(guī)則也適用于這個(gè)函數(shù)的格式字符串和操作。如果發(fā)生錯(cuò)誤,沒有讀取輸入,函數(shù)會(huì)返回EOF,否則將讀取的值的個(gè)數(shù)返回為int類型的值 。,12.8 錯(cuò)誤處理,本書的例子都只包含最起碼的錯(cuò)誤檢查及報(bào)告,因?yàn)橥暾腻e(cuò)誤檢查和報(bào)告代碼會(huì)占用很大的篇幅,使程序看起來相當(dāng)復(fù)雜。然而在實(shí)際的程序中,應(yīng)盡可能地檢查及報(bào)告錯(cuò)誤 。,12.9 再探文本文件

11、操作模式,前面使用的文本模式都是打開文件的默認(rèn)操作模式。在C的早期版本中,可以明確指定文件以文本模式打開。為此,只需在已有的指定符后面加上“t”。因此,除了原來的3 個(gè)模式之外,還有3 個(gè)模式指定符wt、rt和at。這里提及它們,因?yàn)樽x者可能在其他C程序中遇到它們。盡管大多數(shù)編譯器支持它們,但它們不是當(dāng)前C標(biāo)準(zhǔn)的內(nèi)容,所以最好不要在代碼中使用它們 。,12.10 二進(jìn)制文件的輸入輸出,文件操作除了文本模式外,還有一個(gè)二進(jìn)制模式。在這個(gè)模式下,不轉(zhuǎn)換數(shù)據(jù),也不需用格式字符串控制輸入輸出,所以它比文本模式簡(jiǎn)單。二進(jìn)制模式將內(nèi)存的數(shù)據(jù)直接傳送到文件中。文本模式下具有特殊意義的字符,如n和0,在二進(jìn)制

12、模式下就沒有意義了 。 指定二進(jìn)制模式 寫入二進(jìn)制文件 讀取二進(jìn)制文件,12.10.1 指定二進(jìn)制模式,要指定二進(jìn)制模式,只需在基本打開模式指定符后附加b。因此,打開模式指定符wb表示寫入二進(jìn)制文件,rb表示讀取二進(jìn)制文件,ab表示將數(shù)據(jù)追加到二進(jìn)制文件的末尾,rb+表示讀寫二進(jìn)制文件 。,12.10.2 寫入二進(jìn)制文件,寫入二進(jìn)制文件的函數(shù)是fwrite()。最好用一個(gè)例子來解釋它。假設(shè)用下面的語句打開文件,以執(zhí)行寫入操作: char *filename = myfile.bin; FILE *pfile = fopen(filename, wb);,12.10.3 讀取二進(jìn)制文件,二進(jìn)制文

13、件以讀取模式打開后,就可以使用fread()函數(shù)讀取它。使用和寫入二進(jìn)制文件例子中相同的變量讀取文件,語句如下: size_t wcount = fread( pdata, sizeof(long), num_items, pfile);,12.11 讀取二進(jìn)制文件,在許多應(yīng)用程序中,需要能隨機(jī)訪問文件中的數(shù)據(jù),而不是按順序訪問它們。某些信息存儲(chǔ)在文件的中央,因此必須從文件的開頭讀起,直到找到需要的信息為止。但如果文件包含幾百萬項(xiàng),就要花相當(dāng)多的時(shí)間。 文件定位操作 找出我們?cè)谖募械奈恢?在文件中設(shè)定位置,12.11.1 文件定位操作,文件定位有兩個(gè)方面:找出當(dāng)前我們?cè)谖募械奈恢?,然后移?dòng)

14、到文件中某個(gè)特定的位置。前者是后者的基礎(chǔ):如果不知道在文件的什么地方,就不可能知道如何到達(dá)要去的地方 。,12.11.2 找出我們?cè)谖募械奈恢?有兩個(gè)函數(shù)可以指出我們?cè)谖募械奈恢?,它們相?dāng)類似,但并不相同。它們是互補(bǔ)的位置函數(shù)。第一個(gè)函數(shù)是ftell(),它的原型是: long ftell(FILE *pfile);,12.11.3 在文件中設(shè)定位置,ftell()的互補(bǔ)函數(shù)是fseek(),它的原型如下: int fseek(FILE *pfile, long offset, int origin);,12.12 使用臨時(shí)文件,程序執(zhí)行時(shí),常需要一個(gè)工作文件來存儲(chǔ)中間結(jié)果,程序結(jié)束后,就

15、刪除它。本章計(jì)算質(zhì)數(shù)的程序就是一個(gè)例子,文件僅在計(jì)算過程中需要。 使用臨時(shí)文件的函數(shù)有兩個(gè),它們各有優(yōu)缺點(diǎn) 。 創(chuàng)建臨時(shí)文件 創(chuàng)建唯一的文件名,12.12.1 創(chuàng)建臨時(shí)文件,第一個(gè)函數(shù)會(huì)自動(dòng)創(chuàng)建臨時(shí)文件。它的原型如下: FILE *tmpfile(void); 這個(gè)函數(shù)沒有參數(shù),返回臨時(shí)文件的指針。如果因某種原因不能創(chuàng)建這個(gè)文件,例如磁盤滿了,這個(gè)函數(shù)會(huì)返回NULL。這個(gè)文件會(huì)以更新方式創(chuàng)建并打開,所以可以讀寫它。這個(gè)文件在程序結(jié)束后會(huì)自動(dòng)刪除,所以不需要任何整理操作。我們永遠(yuǎn)不知道這個(gè)文件叫什么,12.12.2 創(chuàng)建唯一的文件名,第二個(gè)方法是使用一個(gè)可以提供唯一文件名的函數(shù),這個(gè)臨時(shí)的文件名

16、由程序員指定。函數(shù)的原型如下: char *tmpnam(char *filename);,12.13 更新二進(jìn)制文件,有3個(gè)打開模式可用于更新二進(jìn)制文件: 修改文件的內(nèi)容 從鍵盤讀取記錄 將記錄寫入文件 從文件中讀取記錄 寫入文件 列出文件內(nèi)容 更新已有的文件內(nèi)容,12.13.1 修改文件的內(nèi)容,擴(kuò)展上一個(gè)例子,以使用另外兩個(gè)二進(jìn)制更新模式。本節(jié)要添加功能,以更新文件中的已有記錄,添加記錄或刪除文件。這個(gè)程序相當(dāng)復(fù)雜,所以最好將其操作分解到函數(shù)中。文件仍包含姓名記錄,這樣由姓名和年齡組成的記錄的長(zhǎng)度就互不相同。在修改文件的內(nèi)容時(shí),可以看到因此帶來的復(fù)雜性。,12.13.2 從鍵盤讀取記錄,編

17、寫一個(gè)函數(shù),從stdin中讀取姓名字符串和年齡值,將它們存儲(chǔ)在Record對(duì)象中。該函數(shù)的原型如下: struct Record *getrecord(struct Record *precord); 這個(gè)函數(shù)的參數(shù)是指向已有Record結(jié)構(gòu)對(duì)象的指針,其返回值是該對(duì)象的地址。因此,可以把該函數(shù)的調(diào)用作為Record *類型的變?cè)獋魉徒o另一個(gè)函數(shù) 。,12.13.3 將記錄寫入文件,現(xiàn)在,定義一個(gè)函數(shù),將Record對(duì)象的成員寫入FILE *指針指向的文件中,該函數(shù)的原型如下: void writerecord(struct Record *precord, FILE *pFile); 第一個(gè)

18、參數(shù)是指向Record結(jié)構(gòu)的指針,該結(jié)構(gòu)的姓名和年齡成員要寫入文件。第二個(gè)參數(shù)是文件指針,12.13.4 從文件中讀取記錄,下面是從文件中讀取一個(gè)記錄的函數(shù)的原型: struct Record *readrecord(struct Record *precord, FILE *pFile); 要讀取的文件用第二個(gè)參數(shù)指定,即文件指針。為了方便,返回值是作為第一個(gè)參數(shù)傳送的地址。,12.13.5 寫入文件,下面是將任意個(gè)記錄寫入文件的函數(shù)原型,其中記錄是從鍵盤上輸入的: void writefile(char *filename, char *mode); 第一個(gè)參數(shù)是要寫入的文件名,這表示該函

19、數(shù)要打開文件。第二個(gè)參數(shù)是要使用的文件打開模式。將模式指定為“wb+”,writefile()函數(shù)就會(huì)刪除文件的原始內(nèi)容,再將數(shù)據(jù)寫入文件。如果文件不存在,就用指定的名稱創(chuàng)建一個(gè)文件。如果模式指定為“ab+”,記錄就追加到已有的文件中,如果文件不存在,就創(chuàng)建一個(gè)新文件。,12.13.6 列出文件內(nèi)容,將文件中的記錄輸出到標(biāo)準(zhǔn)輸出流中的函數(shù)原型如下: void listfile(char *filename); 其參數(shù)是文件名,所以函數(shù)要先打開文件,操作完成后關(guān)閉它。,12.13.7 更新已有的文件內(nèi)容,更新文件中的已有記錄增加了復(fù)雜性,因?yàn)槲募械男彰胁煌拈L(zhǎng)度。不能簡(jiǎn)單地覆蓋已有的記錄,因?yàn)橛糜谔鎿Q的記錄可能在原來的空間中放不下。如果新記錄的長(zhǎng)度與原記錄相同,就可以覆蓋它,如果不同,就只能將數(shù)據(jù)寫入一個(gè)新文件。下面是更新文件的函數(shù)的原型: void updatefile(char *filename); 唯一的參數(shù)是文件名,所以該函數(shù)會(huì)查找出要更新的記錄,并打開和關(guān)閉文件。,12.14 更新已有的文件內(nèi)容,12.15 更新已有的文件內(nèi)容,本章的最后將前面所學(xué)的內(nèi)容應(yīng)用于最后一個(gè)程序。這個(gè)程

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論