本章重點
- 為什么使用文件
- 什么是文件
- 文件的打開和關閉
- 文件的順序讀寫
- 文件的隨機讀寫
- 文件讀取結束的判定
為什么使用文件
我們前面學習結構體時,寫通訊錄的程序,當通訊錄運行起來的時候,可以給通訊錄中增加、刪除數 據,此時數據是存放在內存中,當程序退出的時候,通訊錄中的數據自然就不存在了,等下次運行通訊 錄程序的時候,數據又得重新錄入,如果使用這樣的通訊錄就很難受。 我們在想既然是通訊錄就應該把信息記錄下來,只有我們自己選擇刪除數據的時候,數據才不復存在。 這就涉及到了數據持久化的問題,我們一般數據持久化的方法有,把數據存放在磁盤文件、存放到數據 庫等方式。 使用文件我們可以將數據直接存放在電腦的硬盤上,做到了數據的持久化。
什么是文件
在程序設計中我們談的文件可以分為兩類:程序文件和數據文件(從文件功能的角度上來講)。
程序文件
包括源程序文件(后綴為.c),目標文件(window環境后綴為.obj),可執行文件(window環境后綴為.exe)
數據文件
文件的內容不一定是程序,屙屎程序運行時讀寫的數據,比如程序運行需要從中讀取數據的文件,或者輸出內容的文件
本章主要討論數據文件
文件名
一個文件要有唯一的文件標識,以便用戶識別和引用。
文件名包括3各部分:文件路徑+文件名主干+文件后綴
例如:c:code\test.txt
文件標識常被稱為文件名
文件類型
根據數據的組織形式,數據文件被稱為文本文件或者二進制文件。
數據在內存中以二進制的形式存儲,如果不加轉換的輸出到外存,就是二進制文件。
如果要求在外存上以ASCII碼的形式存儲,則需要在存儲前轉換,以ASCII碼字符的形式存儲的文件就是文本文件。
文件緩沖區
ANSIC 標準采用“緩沖文件系統”處理的數據文件的,所謂緩沖文件系統是指系統自動地在內存中為程序 中每一個正在使用的文件開辟一塊“文件緩沖區”。從內存向磁盤輸出數據會先送到內存中的緩沖區,裝 滿緩沖區后才一起送到磁盤上。如果從磁盤向計算機讀入數據,則從磁盤文件中讀取數據輸入到內存緩 沖區(充滿緩沖區),然后再從緩沖區逐個地將數據送到程序數據區(程序變量等)。緩沖區的大小根 據C編譯系統決定的
文件指針
緩沖文件系統中,關鍵的概念是“文件類型指針”,簡稱“文件指針”。 每個被使用的文件都在內存中開辟了一個相應的文件信息區,用來存放文件的相關信息(如文件的名 字,文件狀態及文件當前的位置等)。這些信息是保存在一個結構體變量中的。該結構體類型是由系統 聲明的,取名FILE.
不同的C編譯器的FILE類型包含的內容不完全相同,但是大同小異。 每當打開一個文件的時候,系統會根據文件的情況自動創建一個FILE結構的變量,并填充其中的信息, 使用者不必關心細節。 一般都是通過一個FILE的指針來維護這個FILE結構的變量,這樣使用起來更加方便。 下面我們可以創建一個FILE*的指針變量:
FILE* pf;
定義pf是一個指向FILE類型數據的指針變量。可以使pf指向某個文件的文件信息區(是一個結構體變 量)。通過該文件信息區中的信息就能夠訪問該文件。也就是說,通過文件指針變量能夠找到與它關聯 的文件。
文件的打開和關閉
文件在讀寫之前應該先打開文件,在使用結束之后應該關閉文件。 在編寫程序的時候,在打開文件的同時,都會返回一個FILE*的指針變量指向該文件,也相當于建立了指 針和文件的關系。
ANSIC 規定使用fopen函數來打開文件,fclose來關閉文件。
/* fopen fclose example */#include <stdio.h>int main ()
{FILE * pFile;//打開文件pFile = fopen ("myfile.txt","w");//文件操作if (pFile!=NULL){fputs ("fopen example",pFile);//關閉文件fclose (pFile);}return 0;
}
文件的順序讀寫
功能 函數名 適用于
字符輸入函數 fgetc 所有輸入流
字符輸出函數 fputc 所有輸出流
文本行輸入函數 fgets 所有輸入流
文本行輸出函數 fputs 所有輸出流
格式化輸入函數 fscanf 所有輸入流
格式化輸出函數 fprintf 所有輸出流
二進制輸入 fread 文件 二進制輸出
對比一組函數(面試題)
scanf/fscanf/sscanf
printf/fprintf/sprintf
- scanf/printf是針對標準輸入流、標準輸出流的格式化輸入、輸出語句
- fscanf/fprintf是針對所有輸入流/所有輸出流的格式化輸入/輸出語句
- sscanf是從字符串中讀取格式化的數據
- sprintf是把格式化的數據輸出成字符串
文件的隨機讀寫
fseek--定位文件指針
int fseek ( FILE * stream, long int offset, int origin );
根據文件指針的位置和偏移量來定位文件指針
ftell--返回文件指針相對于起始位置的偏移量
long int ftell(FILE* stream);
rewind--將文件指針的位置返回到起始位置
void rewind(FILE* stream);
文件結束判定
被錯誤使用的feof函數
?牢記:在文件讀取過程中,不能用feof函數的返回值直接來判斷文件的是否結束。
feof 的作用是:當文件讀取結束的時候,判斷是讀取結束的原因是否是:遇到文件尾結束。
1. 文本文件讀取是否結束,判斷返回值是否為 EOF ( fgetc ),或者 NULL ( fgets ) 例如:
- fgetc 判斷是否為 EOF .
- fgets 判斷返回值是否為 NULL .
2. 二進制文件的讀取結束判斷,判斷返回值是否小于實際要讀的個數。 例如:
- fread判斷返回值是否小于實際要讀的個數。?
#include<stdio.h>
int main()
{FILE* pf = fopen("test.txt", "r");if (pf == NULL){perror("open file test.txt");return 0;}//讀文件int ch = 0;while ((ch = fgetc(pf)) != EOF){putchar(ch);}if (ferror(pf)){printf("error\n");}else if (feof(pf)){printf("end of file\n");}fclose(pf);pf = NULL;return 0;
}