C語言文件操作詳解
一、什麼是文件
在程序設計中,我們一般談的文件有兩種:程序文件、數據文件。
程序文件:
包括源程序文件(後綴為.c ),目標文件( windows環境後綴為.obj ) ,可執行程序( windows環境後綴為.exe )。
數據文件:
文件的內容不一定是程序,而是程序運行時讀寫的數據,比如程序運行需要從中讀取數據的文件
或者輸出內容的文件。
數據文件又分為”文本文件“和”二級制文件“
二進制文件:數據在內存中以二進制的形式存儲,如果不加轉換的輸出到外存,這種文件我們是看不懂的是一堆亂七八糟的符號,隻有電腦才可以讀懂。
文本文件:如果要求在外存上以ASCII碼的形式存儲,則需要在存儲前轉換。以ASCII字符的形式
存儲的文件就是文本文件。這種文件我們是看得懂的,例如我們在記事本看到的”字“”字母“”數字“,這樣的文件就是文本文件。
二、文件緩沖區
ANSIC采用”緩沖文件系統“來處理數據文件,系統會為每一個正在使用的文件開辟一塊”文件緩沖區“。當程序從內存向磁盤輸出數據時,會將數據先送到輸出緩沖區中,等輸出緩沖區滿瞭之後,才將數據一起送到磁盤;當程序從磁盤向內存讀數據時,數據會先被送到輸入緩沖區,等輸入緩沖區滿瞭之後,才將數據一起送到磁盤;另外程序結束時,緩沖區的內容也會被送到內存或磁盤。
三、文件指針
每個被使用的文件都在內存中開辟瞭一個相應的文件信息區,用來存放文件的相關信息(如文件的
名字,文件狀態及文件當前的位置等)。這些信息是保存在一個結構體變量中的。該結構體類型是
由系統聲明的,取名FILE。
該結構體聲明如下:
struct _iobuf { char *_ptr; int _cnt; char *_base; int _flag; int _file; int _charbuf; int _bufsiz; char *_tmpfname; }; typedef struct _iobuf FILE;
每當打開一個文件的時候,系統會根據文件的情況自動創建一個FILE結構的變量,我們就可以通
過創建一個FILE的指針來維護這個FILE結構的變量。
FILE* pf;//文件指針變量
四、文件的打開和關閉。
文件的打開用fopen函數,文件的關閉用fclose函數。
它們的原型如下:
FILE * fopen ( const char * filename, const char * mode );
int fclose ( FILE * stream );
filenname:這個參數填的是文件名
mode:這個參數代表要對文件進行的操作
stream:這個參數代表指向要關閉的文件的指針。
文件的操作方式有:
“r”(隻讀):程序從一個文本文件讀入數據,如果指定文件不存在會出錯 。
“w”(隻寫):程序向一個文本文件輸出數據,如果指定文件不存在會建立一個新的文件。
“a”(追加): 向文本文件尾添加數據 ,如果指定文件不存在會出錯
“rb”(隻讀): 程序從一個文件讀入數據,隻不過這個文件是二進制文件,如果指定文件不存在會出錯 。
“wb”(隻寫): 程序向一個文件輸出數據,隻不過這個文件是二進制文件 ,如果指定文件不存在會建立一個新的文件
“ab”(追加): 向一個二進制文件尾添加數據,,如果指定文件不存在會出錯
“r+”(讀寫): 為瞭讀和寫,這個文件是文本文件,如果文件不存在會出錯
“w+”(讀寫): 為瞭讀和寫,如果文件不存在會建立一個新的文件
“a+”(讀寫): 打開一個文件,在文件尾進行讀寫 ,如果文件不存在會建立一個新的文件
“rb+”(讀寫) :為瞭讀和寫,打開一個二進制文件 ,如果文件不存在會出錯
“wb+”(讀寫) :為瞭讀和寫一個二進制文件 ,如果文件不存在會建立一個新的文件
“ab+”(讀寫):在 二進制文件尾進行讀和寫 如果文件不存在會建立一個新的文件
文件的讀寫函數有(這些函數是順序讀寫):
字符輸入函數:fgetc
字符輸出函數:fputc
文本行輸入函數:fgets
文本行輸出函數:fputs
格式化輸入函數:fscanf
格式化輸出函數:fprintf
二進制輸入:fread
二進制輸出:fwrite
下面我們用代碼來體會:
int main() { //打開文件 FILE* pf = fopen("data.txt", "r"); if (pf == NULL) { //如果沒有讀到,返回錯誤信息。 perror("fopen"); return -1; } //讀文件 // //關閉文件 fclose(pf); pf = NULL; return 0; }
我們對data.txt,進行”r“(讀)操作,因為當前文件夾下沒有創建這個文件,所以出錯。
現在我們在當前目錄下,創建一個diata.txt文件夾,並輸入字符”abcd”,使用fgetc函數來讀取數據,這個函數的作用是讀取一個字符後,指針往下一個字符走。
int main() { //打開文件 FILE* pf = fopen("data.txt", "r"); if (pf == NULL) { perror("fopen"); return -1; } //讀文件 char ch = fgetc(pf); printf("%c\n", ch); ch = fgetc(pf); printf("%c\n", ch); //關閉文件 fclose(pf); pf = NULL; return 0; }
結果為:
這是因為剛剛開始時,pf指針首先指向首字符”a“,讀完字符”a“後,pf指針就往下一個字符走,指向瞭字符”b“,讀完”b“後,pf指針繼續往下一個字符走,指向瞭字符”c“。
現在使用fgetc函數來讀取數據,這個函數的作用是讀取一個字符串
int main() { //打開文件 FILE* pf = fopen("data.txt", "r"); if (pf == NULL) { perror("fopen"); return -1; } //讀文件 char arr[20] = { 0 }; fgets(arr, 20, pf); printf("%s", arr); //關閉文件 fclose(pf); pf = NULL; return 0; }
結果是:
這個代碼的意思是從pf指向的那個文件讀取20個字符,存到數組arr中,我們知道文件隻有4個字符,所以當文件不夠要被讀取字符數,程序就隻會把文件中的內容讀完,而不會報錯。
下面我們進行”w“操作,並分別使用fputc、fputs函數
fputc函數
int main() { FILE* pf = fopen("test.txt", "w"); if (NULL == pf) { perror("fopen"); return -1; } //寫文件 fputc('b', pf); fputc('i', pf); fputc('t', pf); //關閉文件 fclose(pf); pf = NULL; return 0; }
我們向test.txt文件進行寫操作,如果我們對一個文件進行寫操作,如果這個文件存在,且有內容,寫操作會將文件的內容銷毀,重新寫入目前我們要寫的內容。因為我們當前文件夾下沒有創建這樣的文件,所以程序自動幫我們創建,我們使用fputs函數,這個函數的作用是向文件寫入一個字符,在這些代碼中,我們分別寫瞭”b“、”i“、”t“這幾個字符
fputs函數
int main() { FILE* pf = fopen("test.txt", "w"); if (NULL == pf) { perror("fopen"); return -1; } //寫文件 //寫一行數據 fputs("hello world\n", pf); fputs("hello bit\n", pf); //關閉文件 fclose(pf); pf = NULL; }
fputs函數的作用是向文件輸出一個字符串。因為這個文件在之前已經創建,且有字符”bit“,現在我們重新進行寫操作,字符”bit“會被銷毀,重新寫入hello world、hello bit這兩個字符串。
fprintf函數
struct S { int n; double d; }; int main() { struct S s = { 100, 3.14 }; FILE* pf = fopen("data.txt", "w"); if (NULL == pf) { perror("fopen"); return -1; } //寫文件 fprintf(pf, "%d %lf", s.n, s.d); //關閉文件 fclose(pf); pf = NULL; }
fprintf函數的作用是向pf指向的那個文件輸出格式化字符(所謂的格式化就是類似於代碼中”%d %lf”的格式),所以這個程序會向文件輸出”100“和”3.140000“.
fscanf函數
struct S { int n; double d; }; int main() { struct S s = { 0 }; FILE* pf = fopen("data.txt", "r"); if (NULL == pf) { perror("fopen"); return -1; } //讀文件 fscanf(pf, "%d %lf", &(s.n), &(s.d)); printf("%d %lf\n", s.n, s.d); //關閉文件 fclose(pf); pf = NULL; }
fscanf函數的作用是從文件中讀取格式化數據,存到內存中,由是一個代碼隻,文件中有”100“和”3.140000“這兩個數據,所以這個程序會將這兩個數據讀到結構體變量s中.
最後兩個函數使用方法與fgetc fputc fgets fputs函數類似,我就不示例瞭,同學們自己來試試吧!!!!!
總結
本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!