




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、第12章 處理文件,如果計算機只能處理存儲在主內(nèi)存中的數(shù)據(jù),則應(yīng)用程序的適用范圍和多樣性就會受到相當大的限制。事實上,所有重要的商業(yè)應(yīng)用程序所需的數(shù)據(jù)量遠遠大于主內(nèi)存所能提供的數(shù)據(jù)量,常常需要具備處理外部設(shè)備(例如固定磁盤)所存儲的數(shù)據(jù)的能力。本章將了解如何處理外部設(shè)備上的文件數(shù)據(jù) 。,12.1 文件的概念,在前面的所有例子中,用戶在執(zhí)行程序時輸入的任何數(shù)據(jù),在程序結(jié)束后都會消失。此時如果用戶要用相同的數(shù)據(jù)執(zhí)行程序,就必須重新輸入一遍。這種方式不僅不方便,還使編程任務(wù)無法完成 。 文件中的位置 文件流,12.1.1 文件中的位置,文件有開頭和結(jié)尾,還有一個當前位置,通常定義為從文件頭到當前位置
2、有多少個字節(jié)數(shù),如圖12-1所示。當前位置就是發(fā)生文件操作(讀寫文件的動作)的地方。當前位置可以移動到文件的其他地方去。新的當前位置可以指定為距離文件開頭的偏移量,或在某些情況下,指定為從前一個當前位置算起的正或負偏移量 。,12.1.2 文件流,C庫提供了讀寫數(shù)據(jù)流的函數(shù)。流是外部數(shù)據(jù)源或數(shù)據(jù)目的地的抽象表示,所以鍵盤、顯示器上的命令行和磁盤文件都是流。因此,可以使用輸入輸出函數(shù)讀寫映射為流的任意外部設(shè)備 。,12. 2 文件訪問,磁盤上的每個文件都有一個名稱,文件命名規(guī)則由操作系統(tǒng)確定。如果一個處理文件的程序只能處理特殊名字的文件,就不是很方便,需要為每個要處理的文件編寫不同的程序。因此,
3、在C語言中處理文件時,程序通過文件指針來引用文件。文件指針是一個抽象指針,關(guān)聯(lián)到一個特定的文件上,所以程序可以在不同的情況下處理不同的文件。文件指針指向表示流的結(jié)構(gòu)。本章的示例使用微軟的Windows文件名。如果使用其他操作系統(tǒng)(例如UNIX)就需要適當?shù)卣{(diào)整文件的名稱 。 打開文件 文件重命名 關(guān)閉文件 刪除文件,12. 2.1 打開文件,將內(nèi)部文件指針變量關(guān)聯(lián)到一個特定的外部文件名稱上的過程稱為打開文件。調(diào)用標準庫函數(shù)fopen()就可以打開文件,該函數(shù)返回特定外部文件的文件指針。fopen()函數(shù)在中定義,它的原型如下: FILE *fopen(char *name, char* mod
4、e);,12. 2.2 文件重命名,在許多情況下都需要對文件進行重命名。例如更新文件的內(nèi)容,創(chuàng)建一個新的、更新過的文件。這需要在創(chuàng)建新的文件后,給它指定一個臨時的文件名,然后刪除舊文件,再將這個臨時的文件名更改成被刪掉的文件名。文件重命名非常簡單,只需使用rename()函數(shù),它的原型如下: int rename(const char *oldname, const char *newname);,12. 2.3 關(guān)閉文件,使用完文件后,需告訴操作系統(tǒng)釋放文件指針,這稱為關(guān)閉文件。這個動作通過調(diào)用函數(shù)fclose()來完成。這個函數(shù)將文件指針作為變元,返回int類型的值。如果成功關(guān)閉文件,就返
5、回0,否則返回EOF。函數(shù)fclose()的使用方式如下: fclose(pfile); /* Close the file associated with pfile */,12. 2.4 刪除文件,現(xiàn)在可以在代碼中創(chuàng)建文件,有時也要編程刪除文件。此時可以使用在中聲明的函數(shù)remove(),其用法如下: remove(pfile.txt); 這行語句會從當前目錄中刪除pfile.txt文件。在調(diào)用函數(shù)remove()刪除文件時,文件不應(yīng)是打開的,否則,調(diào)用函數(shù)remove()的動作取決于具體的C實現(xiàn)方式,請參閱庫文檔說明。 文件的任何動作都需要檢查兩次,尤其是刪除文件的動作 。,12.3 寫
6、入文本文件,打開一個文件以用于寫入數(shù)據(jù)后,就可以在程序的任何地方給它寫入數(shù)據(jù),只要可以訪問fopen()為文件設(shè)置的文件指針即可。如果要在包含多個函數(shù)的任意位置訪問文件,就需要確保文件指針有全局作用域,或可以作為變元傳送給訪問文件的函數(shù) 。,12.4 讀取文本文件,fgetc()函數(shù)與fputc()函數(shù)互補,fgetc()從打開的文本文件中讀取一個字符。它將文件指針作為唯一的變元,如果讀取操作成功,就把讀取的字符返回為int類型;否則,返回EOF。fgetc()函數(shù)的一般用法如下面的語句所示: mchar = fgetc(pfile); /* Reads a character into mc
7、har */,12.5 將字符串寫入文本文件,puts()函數(shù)將字符串寫入stdout,而函數(shù)fputs()會將字符串寫入文本文件。它的原型如下: int fputs(char *pstr, FILE *pfile); 第一個變元是要寫入文件的字符串指針,第二個變元是文件指針。這個函數(shù)的動作有點古怪,它會將字符串寫入文件,直到碰到0字符為止,但是0不會寫入文件。用fputs()寫入文件的不定長的字符串,可以用fgets()將它讀取出來。這是因為它是一個字符寫入操作,不是二進制寫入操作,所以它希望寫入的一行文本以換行符結(jié)束。這個函數(shù)不需要換行符,但是讀取文件(使用互補函數(shù)fgets()時,換行符
8、會非常有用。,12.6 從文本文件中讀入字符串,fputs()的互補函數(shù)是fgets(),它可以從文本文件中讀入一個字符串。其函數(shù)原型如下: char *fgets(char *pstr, int nchars, FILE *pfile); fgets()有3個參數(shù)。它會從pfile所指向的文件將字符串讀入pstr所指向的內(nèi)存。 該函數(shù)會一直從文件中讀取字符串,直到讀到了n字符或讀入nchars1個字符為止 。,12.7 格式化文件的輸入輸出,將字符及字符串寫入文件比較順利,但是在程序中一般有許多其他的數(shù)據(jù)類型。例如,要將數(shù)值數(shù)據(jù)寫入文件,就需要更多的操作;要使文件中的內(nèi)容能讓人看得懂,還需要
9、數(shù)值數(shù)據(jù)的字符表示。而格式化文件的輸入輸出函數(shù)提供了這樣的機制 。 格式化文件輸出 格式化文件輸入,12.7.1 格式化文件的輸出,在第10章討論標準流時,就遇到過格式化文件輸出的函數(shù)。它和printf()語句相同,但有一個額外的參數(shù),名稱也稍有不同。它的用法如下: fprintf(pfile, %12d112d%14f, num1, num2, fnum1); 可以看到,這個函數(shù)名稱比printf()多了一個f(文件),第一個變元是指定輸出目的地的文件指針。顯然,文件指針需要通過調(diào)用fopen()來設(shè)定。其余的變元和printf()相同 。,12.7.2 格式化文件的輸入,使用fscanf(
10、)函數(shù)可以得到格式化文件輸入。例如,從文件pfile讀入3個變量值,可以使用如下語句: fscanf(pfile, %12d%12d%14f, 這個函數(shù)的操作和scanf()對stdin的操作完全相同,只是要從第一個變元指定的文件中得到輸入。scanf()函數(shù)的使用規(guī)則也適用于這個函數(shù)的格式字符串和操作。如果發(fā)生錯誤,沒有讀取輸入,函數(shù)會返回EOF,否則將讀取的值的個數(shù)返回為int類型的值 。,12.8 錯誤處理,本書的例子都只包含最起碼的錯誤檢查及報告,因為完整的錯誤檢查和報告代碼會占用很大的篇幅,使程序看起來相當復(fù)雜。然而在實際的程序中,應(yīng)盡可能地檢查及報告錯誤 。,12.9 再探文本文件
11、操作模式,前面使用的文本模式都是打開文件的默認操作模式。在C的早期版本中,可以明確指定文件以文本模式打開。為此,只需在已有的指定符后面加上“t”。因此,除了原來的3 個模式之外,還有3 個模式指定符wt、rt和at。這里提及它們,因為讀者可能在其他C程序中遇到它們。盡管大多數(shù)編譯器支持它們,但它們不是當前C標準的內(nèi)容,所以最好不要在代碼中使用它們 。,12.10 二進制文件的輸入輸出,文件操作除了文本模式外,還有一個二進制模式。在這個模式下,不轉(zhuǎn)換數(shù)據(jù),也不需用格式字符串控制輸入輸出,所以它比文本模式簡單。二進制模式將內(nèi)存的數(shù)據(jù)直接傳送到文件中。文本模式下具有特殊意義的字符,如n和0,在二進制
12、模式下就沒有意義了 。 指定二進制模式 寫入二進制文件 讀取二進制文件,12.10.1 指定二進制模式,要指定二進制模式,只需在基本打開模式指定符后附加b。因此,打開模式指定符wb表示寫入二進制文件,rb表示讀取二進制文件,ab表示將數(shù)據(jù)追加到二進制文件的末尾,rb+表示讀寫二進制文件 。,12.10.2 寫入二進制文件,寫入二進制文件的函數(shù)是fwrite()。最好用一個例子來解釋它。假設(shè)用下面的語句打開文件,以執(zhí)行寫入操作: char *filename = myfile.bin; FILE *pfile = fopen(filename, wb);,12.10.3 讀取二進制文件,二進制文
13、件以讀取模式打開后,就可以使用fread()函數(shù)讀取它。使用和寫入二進制文件例子中相同的變量讀取文件,語句如下: size_t wcount = fread( pdata, sizeof(long), num_items, pfile);,12.11 讀取二進制文件,在許多應(yīng)用程序中,需要能隨機訪問文件中的數(shù)據(jù),而不是按順序訪問它們。某些信息存儲在文件的中央,因此必須從文件的開頭讀起,直到找到需要的信息為止。但如果文件包含幾百萬項,就要花相當多的時間。 文件定位操作 找出我們在文件中的位置 在文件中設(shè)定位置,12.11.1 文件定位操作,文件定位有兩個方面:找出當前我們在文件中的位置,然后移動
14、到文件中某個特定的位置。前者是后者的基礎(chǔ):如果不知道在文件的什么地方,就不可能知道如何到達要去的地方 。,12.11.2 找出我們在文件中的位置,有兩個函數(shù)可以指出我們在文件中的位置,它們相當類似,但并不相同。它們是互補的位置函數(shù)。第一個函數(shù)是ftell(),它的原型是: long ftell(FILE *pfile);,12.11.3 在文件中設(shè)定位置,ftell()的互補函數(shù)是fseek(),它的原型如下: int fseek(FILE *pfile, long offset, int origin);,12.12 使用臨時文件,程序執(zhí)行時,常需要一個工作文件來存儲中間結(jié)果,程序結(jié)束后,就
15、刪除它。本章計算質(zhì)數(shù)的程序就是一個例子,文件僅在計算過程中需要。 使用臨時文件的函數(shù)有兩個,它們各有優(yōu)缺點 。 創(chuàng)建臨時文件 創(chuàng)建唯一的文件名,12.12.1 創(chuàng)建臨時文件,第一個函數(shù)會自動創(chuàng)建臨時文件。它的原型如下: FILE *tmpfile(void); 這個函數(shù)沒有參數(shù),返回臨時文件的指針。如果因某種原因不能創(chuàng)建這個文件,例如磁盤滿了,這個函數(shù)會返回NULL。這個文件會以更新方式創(chuàng)建并打開,所以可以讀寫它。這個文件在程序結(jié)束后會自動刪除,所以不需要任何整理操作。我們永遠不知道這個文件叫什么,12.12.2 創(chuàng)建唯一的文件名,第二個方法是使用一個可以提供唯一文件名的函數(shù),這個臨時的文件名
16、由程序員指定。函數(shù)的原型如下: char *tmpnam(char *filename);,12.13 更新二進制文件,有3個打開模式可用于更新二進制文件: 修改文件的內(nèi)容 從鍵盤讀取記錄 將記錄寫入文件 從文件中讀取記錄 寫入文件 列出文件內(nèi)容 更新已有的文件內(nèi)容,12.13.1 修改文件的內(nèi)容,擴展上一個例子,以使用另外兩個二進制更新模式。本節(jié)要添加功能,以更新文件中的已有記錄,添加記錄或刪除文件。這個程序相當復(fù)雜,所以最好將其操作分解到函數(shù)中。文件仍包含姓名記錄,這樣由姓名和年齡組成的記錄的長度就互不相同。在修改文件的內(nèi)容時,可以看到因此帶來的復(fù)雜性。,12.13.2 從鍵盤讀取記錄,編
17、寫一個函數(shù),從stdin中讀取姓名字符串和年齡值,將它們存儲在Record對象中。該函數(shù)的原型如下: struct Record *getrecord(struct Record *precord); 這個函數(shù)的參數(shù)是指向已有Record結(jié)構(gòu)對象的指針,其返回值是該對象的地址。因此,可以把該函數(shù)的調(diào)用作為Record *類型的變元傳送給另一個函數(shù) 。,12.13.3 將記錄寫入文件,現(xiàn)在,定義一個函數(shù),將Record對象的成員寫入FILE *指針指向的文件中,該函數(shù)的原型如下: void writerecord(struct Record *precord, FILE *pFile); 第一個
18、參數(shù)是指向Record結(jié)構(gòu)的指針,該結(jié)構(gòu)的姓名和年齡成員要寫入文件。第二個參數(shù)是文件指針,12.13.4 從文件中讀取記錄,下面是從文件中讀取一個記錄的函數(shù)的原型: struct Record *readrecord(struct Record *precord, FILE *pFile); 要讀取的文件用第二個參數(shù)指定,即文件指針。為了方便,返回值是作為第一個參數(shù)傳送的地址。,12.13.5 寫入文件,下面是將任意個記錄寫入文件的函數(shù)原型,其中記錄是從鍵盤上輸入的: void writefile(char *filename, char *mode); 第一個參數(shù)是要寫入的文件名,這表示該函
19、數(shù)要打開文件。第二個參數(shù)是要使用的文件打開模式。將模式指定為“wb+”,writefile()函數(shù)就會刪除文件的原始內(nèi)容,再將數(shù)據(jù)寫入文件。如果文件不存在,就用指定的名稱創(chuàng)建一個文件。如果模式指定為“ab+”,記錄就追加到已有的文件中,如果文件不存在,就創(chuàng)建一個新文件。,12.13.6 列出文件內(nèi)容,將文件中的記錄輸出到標準輸出流中的函數(shù)原型如下: void listfile(char *filename); 其參數(shù)是文件名,所以函數(shù)要先打開文件,操作完成后關(guān)閉它。,12.13.7 更新已有的文件內(nèi)容,更新文件中的已有記錄增加了復(fù)雜性,因為文件中的姓名有不同的長度。不能簡單地覆蓋已有的記錄,因為用于替換的記錄可能在原來的空間中放不下。如果新記錄的長度與原記錄相同,就可以覆蓋它,如果不同,就只能將數(shù)據(jù)寫入一個新文件。下面是更新文件的函數(shù)的原型: void updatefile(char *filename); 唯一的參數(shù)是文件名,所以該函數(shù)會查找出要更新的記錄,并打開和關(guān)閉文件。,12.14 更新已有的文件內(nèi)容,12.15 更新已有的文件內(nèi)容,本章的最后將前面所學(xué)的內(nèi)容應(yīng)用于最后一個程序。這個程
溫馨提示
- 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)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- T-ZZB 3706-2024 石化行業(yè)用不銹鋼閥門鑄件
- T-ZJCX 0047-2024 浙江省法人數(shù)字證書應(yīng)用接口規(guī)范
- 二零二五年度宅基地占用權(quán)轉(zhuǎn)讓協(xié)議
- 獨立董事聘用合同(二零二五年度)-能源行業(yè)節(jié)能減排
- 2025年度門面買賣合同(含廣告位租賃)
- 二零二五年度音樂作品著作權(quán)許可與網(wǎng)絡(luò)播放協(xié)議
- 2025年度校外住宿生安全管理及意外傷害賠償協(xié)議
- 2025年度相鄰宅基地邊界爭議解決與宅基地置換協(xié)議
- 二零二五年度拆除工程合同糾紛解決機制合同
- 二零二五年度自然人個人醫(yī)療設(shè)備貸款合同生效與還款規(guī)定
- 2024年中級消防員考試題庫
- 必考古詩賞析知識點(九年級下冊)-2025年中考語文一輪復(fù)習(xí)
- 2024-2025學(xué)年人教版八年級物理上學(xué)期課后習(xí)題答案
- 遼寧省沈陽市大東區(qū)2024年中考化學(xué)模擬試題一
- 國能遼寧北票 200MW 風(fēng)力發(fā)電項目地質(zhì)災(zāi)害危險性評估報告
- 江蘇省常州市教育學(xué)會2023-2024學(xué)年下學(xué)期八年級數(shù)學(xué)考試卷
- DZ∕T 0214-2020 礦產(chǎn)地質(zhì)勘查規(guī)范 銅、鉛、鋅、銀、鎳、鉬(正式版)
- 2024年瓦斯爆炸事故專項應(yīng)急演練桌面推演腳本
- 2024年遼寧大連中遠海運川崎船舶工程有限公司招聘筆試參考題庫含答案解析
- 《單層廠房鋼結(jié)構(gòu)》
- 八年級下冊二次根式作業(yè)設(shè)計
評論
0/150
提交評論