版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、一、文本流和二進制流二、流文件三、文件的翻開函數(shù)fopen和關閉函數(shù)fclose四、格式讀寫fprintf和fscanf函數(shù)五、出錯測試或去除函(feof,ferror,clearerr)第13章 文 件 1一、文本流和二進制流 內存中的信息會由于程序運行的結束而消失。程序運行的結果需要另外穩(wěn)定的介質加以永久保存,這種可以長期保留數(shù)據(jù)的存儲設備稱為磁盤文件。下面幾種是有影響的存儲方式: 1. ANSI C 運行庫緩沖流的輸出輸出操作 2. C 運行庫低級輸出輸出操作 3. iotream類提供的I/O操作 4. DOS 或WINDOWS API 端口操作 5. Microsoft Founda
2、tion 類庫的文件操作 2在C/C+中流可分為兩類: 1) 文本流(text stream); 1) 二進制流(binary stream) 文本流中的數(shù)據(jù)以字符形式出現(xiàn),文本以行作為結束。 圖 數(shù)據(jù)的流入流出是一個相對概念 流 入 couta 流 入 磁盤 內存 緩沖區(qū) 內存 數(shù)據(jù)區(qū) 鍵盤 stdin stdout顯示器 stderr 打印機 stdprn3二、流文件 流文件是C運行庫函數(shù)中由FILE結構有效處理的硬件設備的邏輯描述。在這個稱為標準文件I/O系統(tǒng)中, 定義了三個文本流: stdin,stdout和stderr。一般對如下前3個標準設備,系統(tǒng)構筑了流文件的索引方式,其相應的非
3、緩沖區(qū)的文件代號一并羅列如下: 硬件設備 預定義的流文件或流對象 設備代號或句柄鍵 盤標準輸入 stdin cin 0 顯示器標準輸出 stdout cout 1顯示器標準錯誤 stderr cerr 2串行口標準輔助 stdaux 3打印機標準打印 stdprn clog 4 4 描述流文件的FILE數(shù)據(jù)結構隨編譯器版本的不同而相異,下面的描述摘自微軟VC 6.0 頭文件stdio.h,該結構的具體聲明如下: struct _iobuf char *_ptr; /1索引數(shù)據(jù)流內容的位置指針 int _cnt; /2當前的定位標志數(shù) char *_base; /3緩沖區(qū)基準位置 int _fl
4、ag; /4文件操作模式標記 int _file; /5文件的代號 int _charbuf; /6字符緩沖信息 int _bufsiz; /7緩沖區(qū)大小 char *_tmpfname; /8臨時文件名;typedef struct _iobuf FILE;5 對于該結構軟件供給商并未逐一指明其中每一數(shù)據(jù)成員的詳細含義,標準輸入輸出函數(shù)的用戶不要冒然直接去操作其中的成員,而通過相應的函數(shù)間接進行。 三個預定義的流文件在vc 6.0的stdio.h中通過通過外部說明語句和宏: extern FILE _iob ;#define stdin (&_iob0)#define stdout (&_i
5、ob1)#define stderr (&_iob2) 就已經(jīng)在內存中構建, 因此不對這三個標準的I/O設備進行建立和去除工作。但其它的流文件需要程序員調用相關的函數(shù),進行規(guī)那么的內存分配和釋放工作。6三、文件的翻開函數(shù)fopen和關閉函數(shù)fclose1. 文件的翻開函數(shù)fopen 文件的翻開函數(shù)fopen是為要操作的磁盤文件對應的數(shù)據(jù)結構分配內存的函數(shù),這是一個構建FILE的數(shù)據(jù)結構變量的初始化函數(shù),系統(tǒng)通過調用類似malloc的堆內存分配函數(shù)完成了FILE型結構變量的內存分配。下面是fopen函數(shù)一個簡約的函數(shù)原型: FILE * fopen (const char *filename,
6、const char *mode); 函數(shù)返回一個指向堆空間的FILE *型的流文件指針。不如確切地說該函數(shù)在堆空間誕生了一個FILE型結構變量。7 兩個const char *型的入口參數(shù)對上面的結構成員執(zhí)行了局部初始化賦值。第一個參數(shù)filename是定位磁盤文件路徑的文件名,該文件名通常是雙引號括起來的只讀字符串。 在使用含路徑的文件名時,注意“的使用,對于硬盤中的文件d:mydocu_1ex.cpp 應寫成 “d:mydocu_1ex1.cpp 或進行如下的初始賦值:const char *filename=d:mydocu_1ex1.cpp; 第二個以只讀字符串的形式出現(xiàn)的參數(shù)mod
7、e,界定文件訪問操作的模式。其有效的取值組合和含義見下一頁 8mode 含義 r 以read only 方式翻開一個文本文件,如果 輸入文件不存在或未找到fopen失敗 w 以write only方式翻開一個文本文件,如果 輸出文件已存在,內容將全覆蓋 a 以寫和append方式在文本文件末尾追加,如 果它不存在那么先建立該文件 r+ 以讀或寫的方式翻開一個必須已經(jīng)存在的文 本文件 w+ 以讀或寫的方式翻開一個空文件,如果給定的 文件名存在原來的內容將被沖洗 a+ 以讀/寫和追加方式翻開文件,如果該文件不存 在那么先建立它9 rb 以只讀方式翻開一個binary輸入文件,如果文件 不存在或未找
8、到fopen失敗 wb 以只寫方式翻開一個二進制輸出文件,如果文件 已存在,內容將全覆蓋 ab 以append方式在binary文件末尾追加,如果它 不存在那么先建立該文件 rb+ 以讀或寫的方式翻開一個必須已經(jīng)存在的二進制 文件 wb+ 以讀或寫的方式翻開一個空binary文件,如果文 件名存在原來的內容將被銷毀 ab+ 以讀和追加方式翻開二進制文件,如果該文件不 存在那么先建立它10 指定文件的缺省操作類型取決于一個全局變量 _fmode,vc6.0 里在頭文件stdlib.h中聲明為extern int _fmode;,系統(tǒng)設置的默認值是文本方式即: _fmode=O_TEXT=0 x4
9、000 如果從文本方式切換為二進制模式,可以在程序中令: _fmode= O_BINARY; 如果在翻開文件發(fā)生錯誤,那么fopen都返回NULL即0,其潛在的原因有: a. 以讀模式翻開一個并不存在的文件 b. 翻開一個無權操作的文件如該文件已標明只讀或隱藏屬性試圖寫追加翻開 c. 以追加方式對文件操作但磁盤空間缺乏112.文件的關閉函數(shù)fclose 函數(shù)fclose專用于釋放由函數(shù)fopen申請的堆空間,及時完成緩沖區(qū)數(shù)據(jù)的到位。fclose的函數(shù)原型為: int fclose (FILE * fp);fclose的函數(shù)原型為:int fclose (FILE * fp); 其中入口形參匹
10、配函數(shù)fopen返回的指針值,函數(shù)fclose調用成功返回數(shù)值0,否那么返回EOF即-1。 該函數(shù)不操作預定義的流文件stdin,stdout和stderr,它們是指向全局結構變量的指針。這樣函數(shù)調用: fclose (fp); 就關閉了先前由fopen函數(shù)翻開的文件指針所對應的堆空間。12四、格式讀寫fprintf和fscanf函數(shù) 1. fprintf輸出函數(shù) fprintf輸出函數(shù)的一般形式為: int fprintf (FILE* pTarget, const char* format, argument_list); int fprintf (流文件的目的地,格式控制串,參量列表);
11、 fprintf函數(shù)格式控制串與printf中的相同。將fprintf 的第一個形參pTarget取為實參stdout,其調用格式相當于printf函數(shù)。即 fprintf (stdout,格式控制串,參量列表); 相當于: printf (格式控制串,參量列表); 13 在使用fprintf將內存數(shù)據(jù)寫到磁盤文件之前,先要指明磁盤文件的目的所在,因此通過fopen函數(shù)的寫模式獲得目標地址。如: FILE *fpWrite= fopen (writeFile , w);如此之后就可以調用的 fprintf 函數(shù).如: fprintf (fpWrite, format, v_list); fpr
12、intf (流文件目的地, 格式控制串, 變量列表);142. fscanf輸入函數(shù) fscanf函數(shù)的一般形式為: int fscanf (FILE* pSource, const char* format, address_list); int fscanf (流文件的來源處, 格式控制串, 變量的地址列表; 將fscanf的第一個形參pSource實參化為stdin,其調用格式相當于scanf函數(shù)。即: fscanf ( stdin, 格式控制串, 變量地址1, 變量地址2 . 變量地址n);相當于: scanf (格式控制串, 變量地址1, 變量地址2 . 變量地址n); 15 在調用
13、fscanf函數(shù)將磁盤源文件中的數(shù)據(jù)送到變量所占住的內存之前,先應指明待讀的磁盤文件,因此借助fopen函數(shù)的讀模式得到數(shù)據(jù)源流的地址如: FILE *fpRead= fopen (readFile, r);如此之后就可以調用輸入函數(shù)fscanf。格式為: fscanf (fpRead, format, address_list);16 例 格式轉換處理一個結構變量.#include typedef struct SData int nLineset; float fAdjust; int nPoint; float fXa; float fYa; float fZa; CData; void
14、 OutputData (const char *filename, const CData &d ) FILE *fp= fopen(filename, w); fprintf (fp,%d,%f,%dn,d.nLineset,d.fAdjust,d.nPoint);/1 fprintf (fp,%f,%f,%fn, d.fXa,d.fYa,d.fZa);/2 fclose (fp); 17void InputData (const char *filename, CData &d ) FILE *fp = fopen (filename, r); fscanf (fp, %d, %f, %
15、d, &d.nLineset, &d. fAdjust, &d.nPoint); fscanf (fp,%f,%f,%f, &d.fXa, &d.fYa, &d.fZa); /2 fclose (fp); 18void main (void) CData s= 1,2,3,4,5,6; OutputData (c:sdata.out, s); CData d; InputData (c:sdata.out, d); OutputData (c:cdata.out, d); 在文件c:cdata.out中輸出結果為: 1,2.000000,3 4.000000,5.000000,6.000000
16、在文件c:sdata.out中輸出結果為: 1,2.000000,3 4.000000,5.000000,6.00000019五、出錯測試或去除函(feof,ferror,clearerr)1. feof函數(shù)測試文件結束標志 feof函數(shù)的原型為: int feof (FILE *stream);該函數(shù)的調用格式常為: while (!feof (stream) 讀寫循環(huán)體;2. ferror函數(shù)測試流中的錯誤 ferror函數(shù)的原型為: int ferror (FILE *stream);3. clearerr函數(shù)去除錯誤標志為0 clearerr函數(shù)原型為: void clearerr (
17、FILE *stream);20六、字符和字符串讀寫函數(shù)七、無格式轉換的讀寫函數(shù)fread和fwrite八、文件的定位九、一個簡單的讀寫存盤程序步驟第13章 文 件 21六、字符和字符串讀寫函數(shù) 1. 讀取單個字符的fgetc函數(shù) fgetc函數(shù)的原型為: int fgetc (FILE * pSrcFile); FILE*型的入口形參指明讀取操作的來源, 實參匹配 fopen翻開的磁盤文件或stdin。 該函數(shù)從磁盤文件的當前位置讀取一個字符, 定位源磁盤文件的位置指針向后移動一個字節(jié)。如果該指針到達文件末尾,fgetc函數(shù)返回EOF。 注意例程getc與函數(shù)fgetc作用相同但可以作為函數(shù)
18、和宏出現(xiàn)。getchar()例程與getc(stdin)一致,亦可以作為函數(shù)和宏出現(xiàn)。 22例fgetc.cpp# include void main(void) FILE* fpGet =fopen (fgetc.cpp,r); if (fpGet=NULL) printf (fopen failedn); return; int i=0; char buffer512; while (feof (fpGet)=0 & i512) buffer i+= fgetc (fpGet); bufferi=0; printf (%sn,buffer); /fclose (fpGet); /程序運行的
19、結果顯示fgetc.cpp在屏幕上 232. 存寫單個字符的fputc函數(shù) fputc函數(shù)的原型為:int fputc (int ch, FILE * pDstFile); fputc函數(shù)的第一個形參ch正是要存寫到第二個形參pDstFile關聯(lián)的磁盤文件中去的字符,該函數(shù)返回第一個入口形參的實參值。 pDstFile匹配一個fopen返回的流文件指針或stdout,調用失敗返回EOF。 24例 fputc.cpp # include void main (void) FILE* fpGet = fopen (fputc.cpp, r); if ( fpGet = NULL) printf (
20、fopen failedn); return; FILE* fpPut = fopen (fputc.xpp,w); if ( fpPut = NULL) printf (fopen failedn); return; while (!feof ( fpGet ) /while (feof (fpGet)=0) fputc (fgetc (fpGet), fpPut); fclose ( fpGet ); fclose ( fpPut ); 25 程序運行之后即將上面的fputc.cpp源程序轉存到fputc.xpp中。 上面單個輸入輸出函數(shù)其返回類型是int型的數(shù)值,雖然處理的是僅一個字節(jié)長
21、的字符。 因此接受這些函數(shù)的結果的變量最好定義成int型變量即: int ch1= fgetc ( pSrcFile ); 函數(shù)一般地會自動進行截斷整型高位數(shù)的處理而只存寫低位。 而能不失包容性地應付占兩個字節(jié)的重要結尾信息EOF(-1)。263. 按行讀文本串fgets函數(shù)函數(shù)fgets的原型為:char * fgets(char *pDstBuffer, int num, FILE * pSrcFile); FILE *型的入口形參pSrcFile定位數(shù)據(jù)的來源,匹配實參stdin或fopen函數(shù)讀模式返回的流文件的指針,從中讀取num-1個字符到char*的入口形參pDstBuffer標
22、明的字符緩沖區(qū),pDstBuffer也就是該函數(shù)的返回地址。 如果在讀取num-1個字符之前遇到換行符n那么讀入結束;然后添補一個0字符,以表示字符串的規(guī)那么結束。 暗地里定位源磁盤文件的位置指針向后移動字符緩沖區(qū)實際擁有的字節(jié)數(shù).pDstBuffer 匹配一個足夠大的字符數(shù)組.27例 fgets.cpp # include void main (void) FILE* fp=fopen ( fgets.cpp,r ); if ( fp=NULL ) printf (fopen failedn); return; char sBuffer128; for ( int k=0;k9;k+ ) i
23、f ( fgets ( sBuffer,128,fp )! = NULL) printf ( %s, sBuffer ); fclose ( fp ); /程序運行的結果顯示 fgets.cpp在屏幕上。284. 按行寫文本串fputs函數(shù) 函數(shù)fputs的原型為: int fputs (const char *pSrcBuffer, FILE * pDstFile); 文本文件的操作一般按行進行,一行一行地讀一行一行地寫,fgets函數(shù)執(zhí)行按行讀的操作,函數(shù)fputs那么按行寫。 fputs函數(shù)將第一個形參定位的只讀字符串送到送到第二個形參指明的目的文件中的當前位置。 如果調用成功函數(shù)返回正
24、數(shù),在出現(xiàn)錯誤時返回EOF。29例 fputs.cpp # include void main(void) FILE* fpRead = fopen (fputs.cpp,r); if ( fpRead = NULL ) printf ( fopen r failedn ); return; FILE* fpWrite = fopen ( fputsw.cpp, w) ; if ( fpWrite = NULL ) printf ( fopen w failedn ); return; 30 char s 81; while ( !feof ( fpRead ) /while ( feof (
25、 fpRead ) = =0) if ( fgets ( s, 81, fpRead )! = NULL ) fputs (s, fpWrite ); printf ( %s, s ); fclose ( fpWrite ); /程序運行顯示fputs.cpp在屏幕上同時拷貝了一個備份在磁盤文件fputsw.cpp中31七、無格式轉換的讀寫函數(shù)fread和fwrite 函數(shù)直接讀寫磁盤文件的二進制數(shù)據(jù),讀寫過程數(shù)據(jù)的信息未發(fā)生轉換。因而空間效率和時間效率都比較高。 1. 函數(shù)fread的原型為: size_t fread (void * pDst, size_t size, size_t it
26、ems , FILE * pSrc); 第一個參數(shù)pDst定位讀取數(shù)據(jù)的存放位置,匹配任意集合類型的起始地址。 第二個參數(shù)size指出數(shù)據(jù)的類型大小; size = sizeof ( type )。 32 第三個參數(shù)items指出數(shù)據(jù)的最大項數(shù),常對應數(shù)組的維數(shù),單一變量或對象常取1。 第四個參數(shù)是FILE * 型的入口形參pSrc,指明讀入數(shù)據(jù)的來源。 fread返回實際讀取的項數(shù),函數(shù)從輸入文件中最多讀取items項數(shù),每一項含有size字節(jié),并將它們放入pDst起始的內存中。 如果錯誤發(fā)生那么所讀的結果是游移的。 與pSrc關聯(lián)的位置指針向后移動實際讀取的字節(jié)數(shù)。332. fwrite存
27、寫函數(shù)函數(shù)fwrite的原型為: size_t fwrite(const void * pSrc, size_t size, size_t items, FILE * pDst ); 一般地fread總是讀取原先由frwite存寫的二進制數(shù)據(jù); 第一個參數(shù)入口形參pSrc定位所寫數(shù)據(jù)的源位置,匹配任意集合類型的起始地址。 第四個參數(shù)入口形參 pDst指向待存寫的目的地即與pDst相關聯(lián)的磁盤文件。 其余兩個參數(shù)同fread函數(shù)。 34 函數(shù)fwrite 返回實際所存寫的數(shù)據(jù)項的個數(shù),如出現(xiàn)錯誤返回值可少于items。 fwrite函數(shù)從pSrc定位地址起盡量轉送items個數(shù)據(jù)項到輸出流文件中
28、,位置指針遞增實際所寫的字節(jié)數(shù)。 上面兩個函數(shù)都存在void*的指針用于寬泛地定位內存的地址,但由于其模糊性必伴隨具有size_t 類型的具體參數(shù)嚴格劃定數(shù)據(jù)的邊界,這是void*型形參函數(shù)的共性。 一般地fread總是讀取原先由frwite 存寫的二進制數(shù)據(jù)。35例直接隨機方式處理結構變量和數(shù)組 #include typedef struct SData int nLineset; float fAdjust; int nPoint; float fXa; float fYa; float fZa; CData; void WriteData ( CData pSrc , int n, FI
29、LE *fpDst ) switch (n) case 1: fwrite ( pSrc, sizeof (CData), 1 ,fpDst); break; default: fwrite ( pSrc, sizeof (CData), n, fpDst ); inline void ReadData (CData* pDst, int n, FILE *fpSrc ) fread ( pDst, sizeof ( CData ),n,fpSrc ); 36void PrintData ( const CData &d ) printf (“%4d,%4.1f,%4d,%4.1f,%4.1f
30、,%4.1fn, d.nLineset, d.fAdjust, d.nPoint, d.fXa, d.fYa, d.fZa); void main (void) CData s = 0,1,2,3,4,5; CData d = 1,2,3,4,5,6, 2,3,4,5,6,7, 3,4,5,6,7,8; FILE* fpWrite = fopen ( c:cdata.dat, w); if ( fpWrite = NULL) printf ( fopen w failedn ); return; WriteData ( &s, 1, fpWrite ); WriteData ( d, 3, f
31、pWrite ); fclose ( fpWrite ); FILE* fpRead = fopen ( c:cdata.dat, r ); 37 if ( fpRead = = NULL ) printf ( fopen r failedn ); return; CData b 4; ReadData ( b, 3, fpRead ); ReadData ( b+3, 1, fpRead ); for ( int k=0; k4; k+ ) PrintData ( bk ); c:cdata.dat文件的長度為4*6*4=96個字節(jié),屏幕顯示結果為: 0, 1.0, 2, 3.0, 4.0,
32、 5.0 1, 2.0, 3, 4.0, 5.0, 6.0 2, 3.0, 4, 5.0, 6.0, 7.0 3, 4.0, 5, 6.0, 7.0, 8.038 fread和fwrite函數(shù)因其void*入口參數(shù)而可以匹配任意類型的變量地址,而稱為隨機讀寫函數(shù)。 但實際上數(shù)據(jù)的類型屬性轉移到size_t參數(shù)上去了,這個size_t參數(shù)n=sizeof (type)協(xié)同函數(shù)在定位好的內存空間中讀寫數(shù)據(jù)。 因此數(shù)據(jù)類型屬性的匹配依然是環(huán)環(huán)相扣不可輕易錯位的。即此類型的函數(shù)操作此類型的數(shù)據(jù)。隨機讀寫應根據(jù)數(shù)據(jù)類型的匹配關系為: void WriteData ( CData*pSrc , int n
33、, FILE * fpDst) fwrite (pSrc,sizeof (CData), n, fpDst); void ReadData (CData* pDst ,int n,FILE * fpSrc) fread (pDst,sizeof(CData), n, fpSrc);39八、文件的定位1. ftell函數(shù)告知當前位置 FILE結構的聲明中有一個char *型指針成員 _ptr即索引數(shù)據(jù)流內容的位置指針,該指針潛在地指向當前文件的位置。 當用戶首次翻開流文件進行讀寫操作時,操作系統(tǒng)把該位置指針設置在文件的開頭。 但特別地以追加方式a翻開文件時,位置指針定位于文件的結尾處。每次讀寫一個字符時,位置指針向前移動一個字符。 如果從文件中讀寫一行文本,位置指針一般移到該行末尾或下一行開始處。40 ftell函數(shù)告知當前位置函數(shù)ftell的原型為: long ftell (FILE * stream); 函數(shù)返回的lo
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 調味品品評師安全宣教考核試卷含答案
- 汽車車身整形修復工操作管理評優(yōu)考核試卷含答案
- 衛(wèi)星通信機務員安全生產意識模擬考核試卷含答案
- 煤層氣排采集輸工安全理論考核試卷含答案
- 粉末冶金模具工QC管理知識考核試卷含答案
- 電鳴樂器調試工崗后能力考核試卷含答案
- 2025吉林長春市南關區(qū)面向社會招聘產業(yè)緊缺人才65人備考題庫附答案
- 禮儀主持人操作安全考核試卷含答案
- 無線電監(jiān)測與設備運維員崗前技能掌握考核試卷含答案
- 偏鎢酸銨制備工崗前生產安全意識考核試卷含答案
- 鍋爐三大安全附件69課件講解
- (湘美版)五年級上冊書法指導練習教案
- 家具回收合同模板
- 福建省福州市2023-2024學年高一上學期期末考試物理試卷2
- 鋼結構生產工藝流程
- 學習方法總結高效學習的技巧與方法
- 綜合醫(yī)院心身疾病診治
- 港口安全生產管理模版
- 產房與兒科交接登記表
- 教你填《廣東省普通高中學生檔案》精編版
- 韓國語topik單詞-初級+中級
評論
0/150
提交評論