程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> c文件編程

c文件編程

編輯:關於C

文件流

文件流有兩種方式:一是文本流,此時數據寫入為字符,這些字符組織為數據行,每一行以換行符結束,對於像int或double這類數據需要先轉換成字符,才能寫入文件中。二是二進制流,二進制流就是寫入實際的值,例如double類型的值在文件中占8個字節。不管是文本流還是二進制流,在文件中都是一連串的自己組成,關鍵在於我們怎麼去解釋這些數據,例如字符'a',在文件中存儲的是其ASCII碼值97,在讀取這個文件時,我們可以當作字符'a',也可以當作整數97,所以還是看以什麼樣的方式去解釋這些數據。

一、文本流
1. fopen
使用fopen函數打開文件,函數原型在stdio.h中定義,函數原型如下:
FILE *fopen(const char *path, const char *mode);
其中mode為文件打開的模式,打開模式有:
r         只讀
r+       可讀可寫
w       只寫,如果文件不存在則創建,如果存在則會清除文件原有數據。
w+     可讀可寫,如果文件不存在則會創建,同r+不同的是,打開時會將清除文件原有數據。
a        在追加方式打開只寫文件,如果文件不存在則創建,默認打開時位置指針指向文件末尾。
a+      以追加方式打開可讀寫文件。
如果操作成功,返回指向該文件的FILE指針,否則返回NULL。
注意:以可讀可寫方式打開文件時,不能在寫入數據後馬上就去讀取數據,因為此時文件讀寫指針位置已經發生了改變,要改變當前讀寫位置,調用rewind函數,函數原型如下:
void rewind(FILE *stream);
rewind函數將文件讀寫指針設置到文件頭處,同樣也可以使用fseek函數,rewind函數等同於fseek(fp, 0, SEEK_SET)。
還有一個理由是,寫入的數據並沒有立即寫入文件中,而是放在緩沖區裡面的,在切換到讀模式時,數據有可能沒有寫入文件中而造成數據的丟失,可以使用fflush函數,將緩沖區中的數據寫入到文件中。
與寫模式切換到讀模式類似,讀模式切換到寫模式時,文件的當前讀寫位置可能和想像的不一樣,導致覆蓋原來的數據,同樣要先修改讀寫位置。

 

 

2. fclose
fclose函數為關閉文件,函數原型如下:
int fclose(FILE *fp);
成功返回0,否則返回EOF。
EOF是一個特殊字符,稱為文件結束字符,在stdio.h中定義。

 

 

3. rename
rename為文件重命名函數,函數原型如下:
int rename(const char *oldpath, const char *newpath);
oldpath為原文件名,newpath為新文件名,如果操作成功返回0,否則返回非0值,調用rename函數時,文件必須關閉,否則會操作失敗。

 

 

4. remove
remove函數為刪除文件,函數原型如下:
int remove(const char *pathname);
同樣在調用remove函數時,文件也必須是關閉的,否則會操作失敗。

 

 

5. fputc
fputc函數將一個字符寫入文件中,如果操作成功,返回寫入的字符,否則返回EOF,函數原型如下:
int fputc(int c, FILE *stream);
實際上,字符並不是一個一個地寫入物理文件的,這樣效率極低。寫入字符是存放在內存中的一個緩沖區裡面的,緩沖區中字符累積到一定的數量後,才一次性將他們寫入文件中。
putc等同於fputc,它們的參數和返回值都相同,只是在標准庫中putc實現為一個宏,fputc為一個函數。

 

 

6. fgetc
fgetc同fputc相反,fgetc從文件中讀取一個字符,如果操作成功,返回讀取到的字符,否則返回EOF,函數原型如下:
int fgetc(FILE *stream);
fgetc也不是每次都操作物理文件的,讀取字符時是一次讀取一整塊數據到緩沖區中,然後fgets操作只是從緩沖區中讀取一個字符,直到緩沖區為空,再讀取一個塊數據到緩沖區中。
同putc一樣,getc等同於fgetc。

 

 

5. fputs
同puts類似,fputs將字符串寫入文本文件中,只是puts是將字符串寫入stdout中,函數原型如下:
int fputs(const char *s, FILE *stream);
如果操作成功返回0,否則返回EOF。
注意:fputs用於將字符串寫入文件中,直到遇到'\0'為止,但是'\0'不會寫入文件中。

 

 

6. fgets
fgets函數從文本文件中讀取字符串,函數原型如下:
char *fgets(char *s, int size, FILE *stream);
注意:fgets從文件中讀取字符串,直到讀取到'\n'字符或讀取到size-1個字符為止,如果讀取到'\n'字符,它會將'\n'字符保留在字符串中,在字符串的末尾會附加上'\0'字符,如果操作成功,返回讀取到的字符串指針,否則返回NULL。

 

 

7. fprintf
同printf類似,printf操作的對象是stdout,而fprintf接收一個FILE指針參數,函數原型如下:
int fprintf(FILE *stream, const char *format, ...);


8. fscanf
fscanf同scanf類似,scanf操作的對象是stdin,fscanf接收一個FILE指針參數,函數原型如下:
int fscanf(FILE *stream, const char *format, ...);
如果讀取錯誤,返回EOF,成功返回讀取到值的個數。

 

 

9. fflush
fflush函數將緩沖區中的數據寫入文件中,函數原型如下:
int fflush(FILE *stream);
成功返回0,失敗返回EOF。


10. 錯誤處理
一般將錯誤信息寫入stderr中,而不是stdout,因為stdout可以重定向,例如:
FILE *fp = NULL;

if ((fp = fopen("test.txt", "r")) == NULL) {
        fprintf(stderr, "Can't open file!!!\n");
        exit(1);
}

 

 

二、二進制流
要指定以二進制模式讀寫文件,只需要在文件打開模式中加上b,例如rb、wb、rb+。
1. fwrite
函數原型如下:
size_t fwrite(const void *ptr, size_t size, size_t nmemb,
              FILE *stream);
fwrite函數並不檢查文件是以文本方式還是二進制方式打開,當然也可以使用fwrite將數據寫入文本文件中,但是結果會讓人很難理解。fwrite實例如下:

FILE *fp = NULL;
int data = 10;

fp = fopen("test", wb);
if (fp != NULL) {
        fwrite(&data, sizeof(int), 1, fp);
}
fwrite函數中的參數size為單個元素的字節數,nmemb為元素個數,所以寫入的總字節數為size * nmemb。

2. fread
函數原型如下:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

3. 隨機訪問文件
很多時候,需要隨機訪問文件中的數據,而不是順序的訪問,這就涉及到修改文件當前的讀寫位置。需要注意的是,不能在追加模式下修改寫操作的位置,因為數據總是寫到文件的末尾,可以修改讀操作的位置。
(1) ftell
ftell函數返回當前讀寫操作的位置,函數原型如下:
long ftell(FILE *stream);

(2) fgetpos
fgetpos同ftell函數是相同的作用,都是返回當前的讀寫操作位置,函數原型如下:
int fgetpos(FILE *stream, fpos_t *pos);
同ftell函數不同的是,讀寫的位置是存儲在參數pos中的,成功返回0,失敗返回非0值,例如:
fpos_t here = 0;
fgetpos(fp, &here);

(3) fsetpos
同fgetpos函數對應的是fsetpos,函數原型如下:
int fsetpos(FILE *stream, fpos_t *pos);
fsetpos只能和fgetpos配合使用,也就是說只能使用fgetpos得到的值作為其中的pos參數,例如:fsetpos(fp, &here);
同fgetpos一樣,成功返回0,失敗返回非0值。

(4) fseek
同ftell函數對應的是fseek,函數原型如下:
int fseek(FILE *stream, long offset, int whence);
第一個參數為文件指針,第二個參數為相對第三個參數的偏移,第三個參數為起始位置,取值有:SEEK_SET、SEEK_CUR和SEEK_END,分別表示文件的開頭,當前位置和文件末尾。


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved