天天看點

檔案操作

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