寫完「C語言」單鏈表/雙向鏈表的建立/遍歷/插入/刪除 後,如何將內存中的鏈表信息及時的保存到文件中,又能夠及時的從文件中讀取出來進行處理,便需要用到”文件“的相關知識點進行文件的輸入、輸出。
其實,就算不懂得鏈表,也完全可以學習”文件“相關知識點,但在此之前最好有”指針“基礎。
本篇文章整理自《C語言程序設計教程--人民郵電出版社》第十二章——文件,以作文件探討。
一、數據流與文件概念
二、文件的打開與關閉
三、文件的順序讀寫
四、文件的隨機讀寫
一、數據流與文件概念
1.數據流
數據的輸入與輸出都必須通過計算機的外圍設備,不同的外圍設備對於數據輸入與輸出的格式和方法有不同的處理方式,這就增加了編寫文件訪問程序的困難程度,而且很容易產生外圍設備彼此不兼容的問題。數據流(Data Stream)用來解決這個問題。
數據流將整個文件內的數據看作一串連續的字符(字節),而沒有記錄的限制。
數據流借助文件指針的移動來訪問數據,文件指針目前所指的位置即是要處理的數據,經過訪問後文件指針會自動向後移動。
每個數據文件後面都有一個文件結束符號(EOF),用來告知該數據文件到此結束,若文件指針指到EOF便表示數據已訪問完畢。
2.文件
“文件”是指存放在外部存儲介質(可以是磁盤、光盤、磁帶等)上的數據集合。操作系統對外部介質上的數據是以文件形式進行管理的。當打開一個文件或者創建一個新文件時,一個數據流和一個外部文件(可能是一個物理設備)相關聯。
C語言支持的是流式文件,即前面提到的數據流,它把文件看作一個字節序列,以字節為單位進行訪問,沒有記錄界限,即數據的輸入和輸出的開始和結束僅受程序控制,而不受物理符號(如回車換行符)控制。
可以從不同角度對文件進行分類
(1)根據文件依附的性質——普通文件和設備文件。
(2)根據文件的組織形式——順序讀寫文件和隨機讀寫文件。
(3)根據文件的存儲形式——ASCII碼文件和二進制文件。
ASCII碼文件和二進制文件的主要區別:
(1)存儲形式:ASCII文件將該數據類型轉換為可在屏幕上顯示的形式存儲,二進制文件是按該數據類型在內存中的存儲形式存儲的。
(2)存儲空間:ASCII所占空間較多,而且所占空間大小與數值大小有關。
(3)讀寫時間:二進制文件讀寫時需要轉換,造成存取速度較慢。ASCII碼文件則不需要。
(4)作用:ASCII碼文件通常用於存放輸入數據及程序的最終結果。二進制文件則不能顯示出來,用於暫存程序的中間結果。
在C語言中,標准輸入設備和標准輸出設備是作為ASCII碼文件處理的,它們分別稱為標准輸入文件和標准輸出文件。
文件和內存的交互處理:
二、文件的打開與關閉
要打開指定的文件可使用fopen()函數
FILE *fopen(char *filename,char *mode);
其中第二個參數mode用來設定要打開的文件類型和指定文件的訪問模式。
文件中的訪問模式:
判斷文件是否正確打開
FILE *fp; fp=fopen("文件目錄","文件中的訪問模式"); if(fp==NULL) { printf("\n不能打開該文件!"); getch(); exit(1); }
關閉文件使用fclose()
int fclose(FILE *fp);
返回值為0則表示關閉成功,若返回非0值則表示有錯誤發生。
由系統打開的標准設備文件,系統會自行關閉。
獲取文件的屬性:
獲取文件描述字:int fileno(FILE *fp);
根據文件描述字獲取對應文件大小:long filelength(int handle_no);
三、文件的順序讀寫
順序讀寫是指將文件從頭到尾逐個數據讀出或寫入。
單字符讀寫函數:fgetc()和fputc():
int fgetc(FILE *fp);
功能為:讀取文件指針fp目前所指文件位置中的字符,讀取完畢,文件指針自動往下移一個字符位置,若文件指針已經到文件結尾,返回-1。
返回值:成功則返回讀取到的字符,失敗返回-1.
fgetc()函數調用中,讀取的文件必須是以讀或讀寫的方式打開的。
int fputc(char ch,FILE *fp);
功能為:把字符ch寫入文件指針fp所指向文件的位置。
返回值:成功時返回字符的ASCII碼,失敗時返回EOF(在stdio.h中,符號常量EOF的值等於-1)。
被寫入的字符可以用寫、讀寫、追加方式打開。
字符串讀寫函數:fgets()和fputs():
char *fgets(char *str,int n,FILE *fp);
功能為:在文件指針fp所指文件位置讀取n個字符並放入str字符數組。
返回值:如果讀不到字符串時返回NULL。
int fputs(char *str,FILE *fp);
功能為:將字符串str寫入文件指針fp所指文件的位置。
返回值:寫入數據成功時返回非0值,寫入失敗時返回EOF。
格式化字符串讀寫函數:fscanf()和fprintf():
int fscanf(FILE *fp,"格式化字符串",【輸入項地址表】);
功能為:從文件指針fp所指向的文件中按照格式字符串指定的格式將文件中的數據送到輸入項地址表中。
返回值:讀取數據成功返回所讀取數據的個數,並將數據按照指定格式存入內存中的變量或數組中,文件指針自動向下移動。讀取失敗返回EOF。
int fprintf(FILE *fp,"格式化字符串",【輸入項地址表】);
功能為:將輸出項表中的變量值按照格式字符串制定的格式輸出到文件指針fp所指向的文件位置。
返回值:成功返回輸出字符數,失敗則返回負值。
數據塊讀寫函數:fread()和fwrite:
int fread(void *buffer,int size,int count,FILE *fp);
功能為:從文件指針fp所指向的文件的當前位置開始,一次讀入size個字節,重復count次,並將讀取到的數據存到buffer開始的內存區中,同時將讀寫位置指針後移size*count次。
返回值:該函數的返回值是實際讀取的count值。
int fwrite(void *buffer,int size,int count,FILE *fp);
功能為:從buffer所指向的內存區開始,一次輸出size個字節,重復count次,並將輸出的數據放入fp所指向的文件中,同時將讀寫位置指針後移size*count次。
返回值:返回實際寫入的數據項個數count。
四、文件的隨機讀寫
隨機讀寫可移動文件內部的位置指針到需要讀寫的位置,再進行讀寫,這種讀寫稱為隨機讀寫。實現文件的隨機讀寫關鍵是要按要求移動位置指針,這成為文件的定位。
void rewind(FILE *fp);
功能為:將文件內部的位置指針移到文件的開始位置。
int fseek(FILE *fp,long offset,int whence);
功能為:文件指針由whence地址移到offset的地址。
返回值:
對應文件的指針偏移,在函數定義中並沒有真正的說明清楚返回值,對於offset當為正數的時候是向文件尾偏移的,當為負數的時候是向文件頭方向偏移的,這裡主要是要注意偏移的大小和文件大小邊界的關系。
當offset是向文件尾方向偏移的時候,無論偏移量是否超出文件尾,fseek都是返回0,當偏移量沒有超出文件尾的時候,文件指針式指向正常的偏移地址的,當偏移量超出文件尾的時候,文件指針是指向文件尾的。並不會返回偏移出錯-1值。
當offset是向文件頭方向偏移的時候,如果offset沒有超出文件頭,是正常偏移,文件指針指向正確的偏移地址,fseek返回值為0.當offset超出文件頭時,fseek返回出錯-1值,文件指針不變還是處於原來的地址。
long ftell(FILE *_File);
功能為:得到流式文件的當前位置,用相對於文件開頭的位移量來表示。由於文件中的位置指針經常移動,人們往往不容易知道其當前位置。用fell函數即可以得到當前位置。
返回值:如果返回-1L,表示出錯。
int putw(int _Ch,FILE *_File);
功能為:將整數_Ch輸出到fp指向的文件。
int __cdecl getw(FILE *_File);
功能為:從磁盤文件都一個整數到內存最為返回值。