1. 程式人生 > >C檔案流

C檔案流

   流式檔案操作

這種方式的檔案操作有一個重要的結構FILE,FILE在stdio.h中定義如下:  以下是引用片段:
typedef struct { 
  int level;  
  unsigned flags;  
  char fd;  
  unsigned char hold;  
  int bsize;  
  unsigned char _FAR *buffer;  
  unsigned char _FAR *curp;  
  unsigned istemp;  
  short token;  
 } FILE; 

  FILE這個結構包含了檔案操作的基本屬性,對檔案的操作都要通過這個結構的指標來進行,此種檔案操作常用的函式如下,下面是這些函式的功能使用說明:

1.1.1           fopen()

功能:開啟流

fopen的原型是:FILE *fopen(const char *filename,const char *mode),fopen實現三個功能:為使用而開啟一個流,把一個檔案和此流相連線,給此流返回一個FILR指標。

引數filename指向要開啟的檔名,mode表示開啟狀態的字串,其取值如下:

l "r" 以只讀方式開啟檔案

l "w" 以只寫方式開啟檔案

l "a" 以追加方式開啟檔案

l "r+" 以讀/寫方式開啟檔案,如無檔案出錯

l "w+" 以讀/寫方式開啟檔案,如無檔案生成新檔案

一個檔案可以以文字模式或二進位制模式開啟,這兩種的區別是:在文字模式中回車被當成一個字元'\n'

,而二進位制模式認為它是兩個字元0x0D,0x0A;如果在檔案中讀到0x1B,文字模式會認為這是檔案結束符,也就是二進位制模型不會對檔案進行處理,而文字方式會按一定的方式對資料作相應的轉換。

系統預設的是以文字模式開啟,可以修改全部變數_fmode的值來修改這個設定,例如_fmode=O_TEXT;就設定預設開啟方式為文字模式;而_fmode=O_BINARY;則設定預設開啟方式是二進位制模式。

我們也可以在模式字串中指定開啟的模式,如"rb"表示以二進位制模式開啟只讀檔案,"w+t"或"wt+"表示以文字模式開啟讀/寫檔案。

此函式返回一個FILE指標,所以申明一個FILE指標後不用初始化,而是用fopen()來返回一個指標並與一個特定的檔案相連,如果成敗,返回NULL

例如:  以下是引用片段:

FILE *fp; 

if(fp=fopen("123.456","wb")) 

  puts("開啟檔案成功"); 

else

puts("開啟檔案成敗");

1.1.2           fclose() 關閉流

fclose()的功能就是關閉用fopen()開啟的檔案,其原型是:int fclose(FILE *fp);如果成功,返回0,失敗返回EOF。

在程式結束時一定要記得關閉開啟的檔案,不然可能會造成資料丟失的情況,我以前就經常犯這樣的錯誤。

例:fclose(fp);

1.1.3           fputc() 寫一個字元到流中

向流寫一個字元,原型是int fputc(int c, FILE *stream); 成功返回這個字元,失敗返回EOF。

例:fputc('X',fp);

1.1.4           fgetc() 從流中讀一個字元

從流中讀一個字元,原型是int fputc(FILE *stream); 成功返回這個字元,失敗返回EOF。

例:char ch1=fgetc(fp);

1.1.5           fseek() 在流中定位到指定的字元

此函式一般用於二進位制模式開啟的檔案中,功能是定位到流中指定的位置,原型是int fseek(FILE *stream, long offset, int whence);如果成功返回0,引數offset是移動的字元數,whence是移動的基準,取值是:

符號常量 值 基準位置

Ø SEEK_SET 0 檔案開頭

Ø SEEK_CUR 1 當前讀寫的位置

Ø SEEK_END 2 檔案尾部

例:fseek(fp,1234L,SEEK_CUR);//把讀寫位置從當前位置向後移動1234位元組(L字尾表示長整數)

fseek(fp,0L,2);//把讀寫位置移動到檔案尾

1.1.6           fputs() 寫字串到流

寫一個字串到流中,原型int fputs(const char *s, FILE *stream);

例:fputs("I Love You",fp);

1.1.7           fgets() 從流中讀一行或指定個字元

從流中讀一行或指定個字元,原型是char *fgets(char *s, int n, FILE *stream); 從流中讀取n-1個字元,除非讀完一行,引數s是來接收字串,如果成功則返回s的指標,否則返回NULL。

例:如果一個檔案的當前位置的文字如下:

Love ,I Have

But ……..

如果用

fgets(str1,4,file1);

則執行後str1="Lov",讀取了4-1=3個字元,而如果用

fgets(str1,23,file1);

則執行str="Love ,I Have",讀取了一行(不包括行尾的'\n')。

1.1.8           fprintf() 按格式輸出到流

按格式輸入到流,其原型是int fprintf(FILE *stream, const char *format[, argument, …]);其用法和printf()相同,不過不是寫到控制檯,而是寫到流罷了。

例:fprintf(fp,"-%s",4,"Hahaha");

1.1.9           fscanf() 從流中按格式讀取

從流中按格式讀取,其原型是int fscanf(FILE *stream, const char *format[, address, …]);其用法和scanf()相同,不過不是從控制檯讀取,而是從流讀取罷了。

例:fscanf(fp,"%d%d" ,&x,&y);

1.1.10      feof() 到達檔案尾時返回真值

檢測是否已到檔案尾,是返回真,否則返回0,其原型是int feof(FILE *stream);

例:if(feof(fp))printf("已到檔案尾");

1.1.11      ferror() 發生錯誤時返回其值

原型是int ferror(FILE *stream);返回流最近的錯誤程式碼,可用clearerr()來清除它,clearerr()的原型是void clearerr(FILE *stream);

例:printf("%d",ferror(fp));

1.1.12      rewind() 復位檔案定位器到檔案開始處

把當前的讀寫位置回到檔案開始,原型是void rewind(FILE *stream);其實本函式相當於fseek(fp,0L,SEEK_SET);

例:rewind(fp);

1.1.13      remove() 刪除檔案

刪除檔案,原型是int remove(const char *filename); 引數就是要刪除的檔名,成功返回0。

例:remove("c:\\io.sys");

1.1.14      fread() 從流中讀指定個數的字元

從流中讀指定個數的字元,原型是size_t fread(void *ptr, size_t size, size_t n, FILE *stream);引數ptr是儲存讀取的資料,void*的指標可用任何型別的指標來替換,如char*、int *等等來替換;size是每塊的位元組數;n是讀取的塊數,如果成功,返回實際讀取的塊數(不是位元組數),本函式一般用於二進位制模式開啟的檔案中。

例:

以下是引用片段:
char x[4230]; 
FILE *file1=fopen("c:\\msdos.sys","r"); 
fread(x,200,12 ,file1);//
共讀取200*12=2400個位元組

1.1.15      fwrite() 向流中寫指定個數的字元

與fread對應,向流中寫指定的資料,原型是size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream);引數ptr是要寫入的資料指標,void*的指標可用任何型別的指標來替換,如char*、int *等等來替換;size是每塊的位元組數;n是要寫的塊數,如果成功,返回實際寫入的塊數(不是位元組數),本函式一般用於二進位制模式開啟的檔案中。

例:

以下是引用片段:
  char x[]="I Love You"; 
  fwire(x, 6,12,fp);//寫入6*12=72位元組 
  將把"I Love"寫到流fp中12次,共72位元組

1.1.16      tmpfile() 生成一個臨時檔案流

其原型是FILE *tmpfile(void); 生成一個臨時檔案,以"w+b"的模式開啟,並返回這個臨時流的指標,如果失敗返回NULL。在程式結束時,這個檔案會被自動刪除。

例:FILE *fp=tmpfile();

1.1.17      tmpnam() 生成一個唯一的檔名

其原型為char *tmpnam(char *s); 生成一個唯一的檔名,其實tmpfile()就呼叫了此函式,引數s用來儲存得到的檔名,並返回這個指標,如果失敗,返回NULL。

例:tmpnam(str1);

1.2    I/O檔案操作

這是C提供的另一種檔案操作,它是通過直接存/取檔案來完成對檔案的處理,而上篇所說流式檔案操作是通過緩衝區來進行;流式檔案操作是圍繞一個FILE指標來進行,而此類檔案操作是圍繞一個檔案的“控制代碼”來進行,什麼是控制代碼呢?它是一個整數,是系統用來標識一個檔案(在WINDOWS中,控制代碼的概念擴充套件到所有裝置資源的標識)的唯一的記號。此類檔案操作常用的函式如下表,這些函式及其所用的一些符號在io.h和fcntl.h中定義,在使用時要加入相應的標頭檔案。

下面就對這些函式一一說明:

1.2.1           open()開啟一個檔案並返回它的控制代碼

開啟一個檔案並返回它的控制代碼,如果失敗,將返回一個小於0的值,原型是int open(const char *path, int access [, unsigned mode]); 引數path是要開啟的檔名,access是開啟的模式,mode是可選項。表示檔案的屬性,主要用於UNIX系統中,在DOS/WINDOWS這個引數沒有意義。其中檔案的開啟模式如下表。

符號含義

l O_RDONLY 只讀方式

l O_WRONLY 只寫方式

l O_RDWR 讀/寫方式

l O_NDELAY 用於UNIX系統

l O_APPEND 追加方式

l O_CREAT 如果檔案不存在就建立

l O_TRUNC 把檔案長度截為0

l O_EXCL 和O_CREAT連用,如果檔案存在返回錯誤

l O_BINARY 二進位制方式

l O_TEXT 文字方式

對於多個要求,可以用"|"運算子來連線,如O_APPEND|O_TEXT表示以文字模式和追加方式開啟檔案。

例:int handle=open("c:\\msdos.sys",O_BINARY|O_CREAT|O_WRITE)

1.2.2           close()關閉一個控制代碼

關閉一個控制代碼,原型是int close(int handle);如果成功返回0。

例:close(handle)

1.2.3           lseek()定位到檔案的指定位置

定位到指定的位置,原型是:long lseek(int handle, long offset, int fromwhere);引數offset是移動的量,fromwhere是移動的基準位置,取值和前面講的fseek()一樣,SEEK_SET:檔案首部;SEEK_CUR:檔案當前位置;SEEK_END:檔案尾。此函式返回執行後文件新的存取位置。例:

lseek(handle,-1234L,SEEK_CUR);//把存取位置從當前位置向前移動1234個位元組。

x=lseek(hnd1,0L,SEEK_END);//把存取位置移動到檔案尾,x=檔案尾的位置即檔案長度

1.2.4           read()塊讀檔案

從檔案讀取一塊,原型是int read(int handle, void *buf, unsigned len);引數buf儲存讀出的資料,len是讀取的位元組。函式返回實際讀出的位元組。

例:char x[200];read(hnd1,x,200);

1.2.5           write()塊寫檔案

寫一塊資料到檔案中,原型是int write(int handle, void *buf, unsigned len);引數的含義同read(),返回實際寫入的位元組。

例:char x[]="I Love You";write(handle,x,strlen(x));

1.2.6           eof()測試檔案是否結束

類似feof()測試檔案是否結束,是返回1,否則返回0;原型是:int eof(int handle);

例:while(!eof(handle1)){……};

1.2.7           filelength()取得檔案長度

返回檔案長度,原型是long filelength(int handle);相當於lseek(handle,0L,SEEK_END)

例:long x=filelength(handle);

1.2.8           rename()重新命名檔案

重新命名檔案,原型是int rename(const char *oldname, const char *newname); 引數oldname是舊檔名,newname是新檔名。成功返回0

例:rename("c:\\config.sys","c:\\config.w40");

1.2.9           chsize();改變檔案長度