C++通過以下幾個類支援檔案的輸入輸出
(1) ofstream:寫操作,輸出檔案類;
(2) ifstream:讀操作,輸入檔案類;
(3) fstream:可同時讀寫的檔案類。
1. open函數:打開檔案
函數原型:void open(const char*filename,int mode,int access);
參數說明:filename: 要打開的檔案名
mode: 要打開檔案的方式
access: 打開檔案的屬性
打開檔案的方式在類
iOS(是所有流式I/O類的基類)中定義,常用的值如下:
ios::app: 以追加的方式打開檔案
ios::ate: 檔案打開後定位到檔案尾,ios:app就包含有此屬性
ios::binary: 以二進制方式打開檔案,預設的方式是文本方式。兩種方式的差別見前文
ios::in: 檔案以輸入方式打開
ios::out: 檔案以輸出方式打開
ios::nocreate: 不建立檔案,是以檔案不存在時打開失敗
ios::noreplace:不覆寫檔案,是以打開檔案時如果檔案存在失敗
ios::trunc: 如果檔案存在,把檔案長度設為0
可以用“或”把以上屬性連接配接起來,如ios::out|ios::binary
打開檔案的屬性取值是:
0:普通檔案,打開通路
1:隻讀檔案
2:隐含檔案
4:系統檔案
例如:以二進制輸入方式打開檔案c:\config.sys
fstreamfile1;
file1.open("c:\\config.sys",ios::binary|ios::in,0);
ofstream file;
file.open ("example.bin", ios::out |ios::app | ios::binary);
2. close函數
函數原型:void close()
3. 二進制檔案(Binary files)
在二進制檔案中,使用<< 和>>,以及函數(如getline)來操作符輸入和輸出資料,沒有什麼實際意義,雖然它們是符合文法的。
檔案流包括兩個為順序讀寫資料特殊設計的成員函數:write 和 read。第一個函數 (write) 是ostream 的一個成員函數,都是被ofstream所繼承。而read 是istream 的一個成員函數,被ifstream 所繼承。類 fstream 的對象同時擁有這兩個函數。它們的原型是:
write ( char *buffer, streamsize size );
read ( char * buffer, streamsize size );
這裡 buffer 是一塊記憶體的位址,用來存儲或讀出資料。參數size 是一個整數值,表示要從緩存(buffer)中讀出或寫入的字元數。
2.1 檔案打開與關閉
[ fopen ][ fclose ]
2.1.1 fopen(打開檔案)
頭檔案: #include<cstdio>
函數聲明: FILE * fopen(const char * path,const char * mode);
參數:
- path字元串 包含欲打開的檔案路徑及檔案名如果沒有指定檔案路徑,則預設為目前工作目錄
- mode字元串
使用方式 具體含義
“rt” 隻讀打開一個文本檔案,隻允許讀資料
“wt” 隻寫打開或建立一個文本檔案,隻允許寫資料
“at” 追加打開一個文本檔案,并在檔案末尾寫資料
“rb” 隻讀打開一個二進制檔案,隻允許讀資料
“wb” 隻寫打開或建立一個二進制檔案,隻允許寫資料
“ab” 追加打開一個二進制檔案,并在檔案末尾寫資料
“rt+” 讀寫打開一個文本檔案,允許讀和寫
“wt+” 讀寫打開或建立一個文本檔案,允許讀寫
“at+” 讀寫打開一個文本檔案,允許讀,或在檔案末追加資料
“rb+” 讀寫打開一個二進制檔案,允許讀和寫
“wb+” 讀寫打開或建立一個二進制檔案,允許讀和寫
“ab+” 讀寫打開一個二進制檔案,允許讀,或在檔案末追加資料
檔案使用方式由r,w,a,t,b,+六個字元拼成,各字元的含義是:
- r(read): 讀 (打開隻讀檔案,該檔案必須存在)
- w(write): 寫 (打開隻寫檔案,若檔案存在則檔案長度清為0,即該檔案内容會消失.若檔案不存在則建立該檔案)
- a(append): 追加(以附加的方式打開隻寫檔案.若檔案不存在,則會建立該檔案,如果檔案存在,寫入的資料會被加到檔案尾,即檔案原先的内容會被保留)
- t(text): 文本檔案,可省略不寫
- b(banary): 二進制檔案
- +: 可讀和寫
說明:
- 上述的形态字元串都可以再加一個 b 字元,如 rb、w+b 或 ab+ 等組合,加入 b 字元用來告訴函數庫打開的檔案為二進制檔案,而非純文字檔案.不過在 POSIX 系統,包含 Linux 都會忽略該字元.由 fopen() 所建立的新檔案會具有 S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH(0666) 權限,此檔案權限也會參考 umask 值.
- 使用 fopen() 函數打開的檔案會先将檔案複制到緩沖區.注意:所下達的讀取或寫入動作,都是針對緩沖區進行存取而不是磁盤,隻有當使用 fclose() 函數關閉檔案時,緩沖區中的資料才會寫入磁盤.
傳回值: 檔案順利打開後,指向該流的檔案指針就會被傳回.若果檔案打開失敗則傳回 NULL , 并把錯誤代碼存在 errno 中.(附加說明 一般而言,開檔案後會作一些檔案讀取或寫入的動作,若開檔案失敗,接下來的讀寫動作也無法順利進行,是以在 fopen() 後請作錯誤判斷及處理.)
2.1.2 fclose(關閉檔案)
函數聲明: int fclose(FILE * stream);
說明: fclose() 用來關閉先前 fopen() 打開的檔案.此動作會讓緩沖區内的資料寫入檔案中,并釋放系統所提供的檔案資源.
傳回值:
- 若關檔案動作成功則傳回 0 ,有錯誤發生時則傳回 EOF 并把錯誤代碼存到 errno.
- 錯誤代碼 EBADF 表示參數 stream 非已打開的檔案.
2.2 檔案的讀寫
fgetc fputc fgets fputs fread fwrite fprintf 與 fscanf getc getchar gets putc putchar puts ungetc
對檔案的讀和寫是最常用的檔案操作.在C語言中提供了多種檔案讀寫的函數:(使用以下函數都要求包含頭檔案cstdio.)
- 字元讀寫函數 :fgetc 和 fputc
- 字元串讀寫函數:fgets 和 fputs
- 資料塊讀寫函數:freed 和 fwrite
- 格式化讀寫函數:fscanf 和 fprinf
2.2.1 fgetc (由檔案中讀取一個字元)
頭檔案: include<cstdio>
函數聲明: int fgetc(FILE * stream);
- fgetc()從參數stream所指的檔案中讀取一個字元.若讀到檔案尾而無資料時便傳回EOF.
- 字元讀取函數fgetc()可從檔案資料流中一次讀取一個字元,然後讀取光标移動到下一個字元,并逐漸将檔案的内容讀出
例子解析:
int ch;
ch=fgetc(fp);
其意義是從打開的檔案fp中讀取一個字元并送入 ch 中.
對于fgetc函數的使用有以下幾點說明:
應注意檔案指針和檔案内部的位置指針不是一回事.
- 在fgetc函數調用中,讀取的檔案必須是以讀或讀寫方式打開的.
- 讀取字元的結果也可以不向字元變量指派 (例如: fgetc(fp); 但是讀出的字元不能儲存)
- 在檔案内部有一個位置指針,用來指向檔案的目前讀寫位元組位置,在檔案打開時,該指針總是指向檔案的第一個位元組.使用fgetc 函數後,該位置指針将向後移動一個位元組. 是以可連續多次使用fgetc函數,讀取多個字元.
- 檔案指針是指向整個檔案的,須在程式中定義說明,隻要不重新指派,檔案指針的值是不變的.
- 檔案内部的位置指針用以訓示檔案内部的目前讀寫位置,每讀寫一次,該指針均向後移動,它不需在程式中定義說明,有系統自動設定而是的.
傳回值 : getc() 會傳回讀取到的字元,若傳回 EOF 則表示到了檔案尾
2.2.2 fputc(将一指定字元寫入檔案流中)
函數聲明: int fputc(int c,FILE * stream);
- fputc 會将參數c 轉為 unsigned char 後寫入參數 stream 指定的檔案中.
- 其意 putc 函數的使用幾點說明:
- 被寫入的檔案可以用寫、讀寫、追加方式打開,用寫或讀寫方式,寫入字元時是從檔案首開始的.如需保留原有檔案内容,希望寫入的字元,被寫入的檔案若不存在,則建立該檔案.
- 每寫入一個字元,檔案内部位置指針向後移動一個位元組.
- fputc 函數有一個傳回值,如寫入成功則傳回寫入的字元,否則傳回一個 EOF .可用此來判斷寫符,寫入一個檔案,再把該檔案内容讀出顯示在螢幕上.
傳回值: fputc() 會傳回寫入成功的字元,即參數 c.若傳回 EOF 則代表寫入失敗.
2.2.3 fgets(由檔案中讀取一字元串)
函數聲明: char * fgets(char * s,int size,FILE * stream);
說明: fgets() 用來從參數 stream 所指的檔案内讀入字元并存到參數 s 所指的記憶體空間,直到出現換行字元、讀到檔案尾或是已讀了size-1個字元為止,最後會加上 NULL 作為字元串結束.
傳回值: gets() 若成功則傳回 s 指針,傳回 NULL 則表示有錯誤發生.
2.2.4 fputs(将一指定的字元串寫入檔案内)
函數聲明: int fputs(const char * s,FILE * stream);
說明: fputs() 用來将參數 s 所指的字元串寫入到參數 stream 所指的檔案内.
傳回值: 若成功則傳回寫出的字元個數,傳回 EOF 則表示有錯誤發生.
2.2.5 fread(從檔案流讀取資料)
函數聲明: size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream);
說明: fread() 用來從檔案流中讀取資料
- stream 為已打開的檔案指針
- ptr 指向欲存放讀取進來的資料空間,讀取的字元數以參數 size*nmemb 來決定.Fread() 會傳回實際讀取到的 nmemb 數目,如果此值比參數 nmemb 來得小,則代表可能讀到了檔案尾或有錯誤發生,這時必須用 feof() 或 ferror() 來決定發生什麼情況.
傳回值: 傳回實際讀取到的nmemb數目.
2.2.6 fwrite(将資料寫至檔案流)
函數聲明: size_t fwrite(const void * ptr,size_t size,size_t nmemb,FILE * stream);
說明:
- fwrite() 用來将資料寫入檔案流中
- fprintf 和 fscanf 函數的讀寫對象不是終端(标準輸入輸出),而是磁盤檔案
- ptr 指向欲寫入的資料位址,總共寫入的字元數以參數 size*nmemb 來決定.Fwrite() 會傳回實際寫入的 nmemb 數目.
傳回值: 傳回實際寫入的 nmemb 數目.
2.2.7 fprintf 與 fscanf(将指定字元寫磁盤檔案)
函數聲明:
- _CRTIMP int __cdecl fprintf(FILE *, const char *, ...);
- _CRTIMP int __cdecl fscanf(FILE *, const char *, ...);
說明: 它們與 printf 和 scanf 函數相仿,都是格式化讀寫函數.不同的是:fprintf 和 fscanf 函數的讀寫對象不是終端(标準輸入輸出),而是磁盤檔案.printf 函數是将内容輸出到終端(螢幕),是以,fprintf 就是将内容輸出到磁盤檔案了
2.2.8 getc(由檔案中讀取一個字元)
函數聲明: int getc(FILE * stream);
- getc() 用來從參數 stream 所指的檔案中讀取一個字元.若讀到檔案尾而無資料時便傳回 EOF
- getc() 與 fgetc() 作用相同,但 getc() 為宏定義,非真正的函數調用.
傳回值: getc() 會傳回讀取到的字元,若傳回 EOF 則表示到了檔案尾.
2.2.9 getchar(由标準輸入裝置内讀進一字元)
函數聲明: int getchar(void);
- getchar() 用來從标準輸入裝置中讀取一個字元.然後将該字元從 unsigned char 轉換成 int 後傳回
- getchar() 非真正函數,而是 getc(stdin) 宏定義
傳回值: getchar()會傳回讀取到的字元,若傳回EOF則表示有錯誤發生.
2.2.10 gets(由标準輸入裝置内讀進一字元串)
函數聲明: char * gets(char *s);
說明: gets() 用來從标準裝置讀入字元并存到參數 s 所指的記憶體空間,直到出現換行字元或讀到檔案尾為止,最後加上 NULL 作為字元串結束,由于 gets() 無法知道字元串 s 的大小,必須遇到換行字元或檔案尾才會結束輸入,是以容易造成緩沖溢出的安全性問題.建議使用 fgets() 取代
傳回值: gets() 若成功則傳回 s 指針,傳回 NULL 則表示有錯誤發生.
2.2.11 putc(将一指定字元寫入檔案中)
頭檔案: #include<cstdio>
函數聲明: int putc(int c,FILE * stream);
- putc() 會将參數 c 轉為 unsigned char 後寫入參數 stream 指定的檔案中
- putc() 與 fputc()作用相同,但 putc() 為宏定義,非真正的函數調用.
傳回值: putc() 會傳回寫入成功的字元,即參數 c.若傳回 EOF 則代表寫入失敗.
2.2.12 putchar(将指定的字元寫到标準輸出裝置)
函數聲明: int putchar (int c);
- putchar() 用來将參數 c 字元寫到标準輸出裝置.
- putchar() 非真正函數,而是 putc(c,stdout) 宏定義.
傳回值: putchar() 會傳回輸出成功的字元,即參數 c.若傳回 EOF 則代表輸出失敗.
2.2.13 puts(由标準輸入裝置内讀進一字元串)
函數聲明: int puts(char *s);
說明: 把函數的字元串寫到标準輸出流 stdout,在輸出流中用換行符('\n')替換字元串中的結束符null 字元('\0 ')
傳回值: puts() 若成功則傳回正的非零值,傳回 EOF 則表示有錯誤發生.
2.2.14 ungetc(将指定字元寫回檔案流中)
函數聲明: int ungetc(int c,FILE * stream);
說明: ungetc() 将參數 c 字元寫回參數 stream 所指定的檔案流.這個寫回的字元會由下一個讀取檔案流的函數取得.
傳回值: 成功則傳回 c 字元,若有錯誤則傳回 EOF.
2.3 檔案的緩沖區操作:
fflush ] [ setbuf setbuffer setlinebuf setvbuf
2.3.1 fflush(更新緩沖區)
函數聲明: int fflush(FILE* stream);
說明: fflush() 會強迫将緩沖區内的資料寫回參數 stream 指定的檔案中.如果參數 stream 為 NULL ,fflush() 會将所有打開的檔案資料更新.
傳回值: 成功傳回 0 ,失敗傳回 EOF ,錯誤代碼存于errno中.(錯誤代碼: EBADF 參數 stream 指定的檔案未被打開,或打開狀态為隻讀)
2.3.2 setbuf(設定檔案流的緩沖區)
函數聲明: void setbuf(FILE * stream,char * buf);
說明: 在打開檔案流後,讀取内容之前,調用 setbuf() 可以用來設定檔案流的緩沖區
- stream為指定的檔案流
- buf 指向自定的緩沖區起始位址.如果參數 buf 為 NULL 指針,則為無緩沖 IO .Setbuf() 相當于調用 setvbuf(stream,buf,buf?_IOFBF:_IONBF,BUFSIZ)
2.3.3 setbuffer(設定檔案流的緩沖區)
函數聲明: void setbuffer(FILE * stream,char * buf,size_t size);
說明: 在打開檔案流後,讀取内容之前,調用 setbuffer() 可用來設定檔案流的緩沖區.
- stream 為指定的檔案流
- buf 指向自定的緩沖區起始位址
- size 為緩沖區大小
2.3.4 setlinebuf(設定檔案流為線性緩沖區)
函數聲明: void setlinebuf(FILE * stream);
說明: setlinebuf() 用來設定檔案流以換行為依據的無緩沖 IO.相當于調用 setvbuf(stream,(char * )NULL,_IOLBF,0);
2.3.5 setvbuf(設定檔案流的緩沖區)
函數聲明: int setvbuf(FILE * stream,char * buf,int mode,size_t size);
說明: 在打開檔案流後,讀取内容之前,調用 setvbuf() 可以用來設定檔案流的緩沖區
-
- mode取值有下列幾種:
- _IONBF 無緩沖 IO
- _IOLBF 以換行為依據的無緩沖 IO
- _IOFBF 完全無緩沖 IO.如果參數 buf 為 NULL 指針,則為無緩沖 IO