文件操作
什么是文件
程序文件
數據文件
文件名
文件的打開和關閉
文件指針
文件的打開和關閉
==打開方式==
在程序目錄下面沒有data.txt文件
在程序目錄下面有data.txt文件
data放在桌面
同理寫文件
==注意這個w也不是誰便用的==
文件操作
什么是文件
程序文件
數據文件
文件名
文件的打開和關閉
文件指針
文件的打開和關閉
==打開方式==
在程序目錄下面沒有data.txt文件
在程序目錄下面有data.txt文件
data放在桌面
同理寫文件
==注意這個w也不是誰便用的==
文件的順序讀寫
fputc寫字符函數
==流==
fgetc讀字符函數
注意
fputs寫字符串函數
同樣適用所有輸出流
fgets讀字符串函數
同理適應所有輸入流
fprintf格式化輸出函數
同理他適用所有輸出流
fscanf格式化輸入函數
同理適用所有輸入流
fwrite二進制輸出函數
==抱歉的是他只適用于文件流==
fread二進制輸入
==和fwrite一樣他只適用于文件流==
對比一組函數
scanf/fscanf/sscanf
sscanf
printf/fprintf/sprintf
sprintf
文件的隨機讀寫
fseek
ftell
rewind
文本文件和二進制文件
一個數據在內存中是怎么存儲的呢?
文件讀取結束的判定
fgetc
被錯誤使用的feof
文件緩沖區
這里可以得出一個結論:
文件操作
什么是文件
磁盤上的文件是文件
但是在程序設計中,我們一般談的文件有兩種:程序文件,數據文件(從文件功能的角度來分類的)
程序文件
包括源程序文件(后綴為.c).目標文件(windows環境后綴為.obj),可執行文件(windows環境后綴為.exe)
數據文件
文件內容不一定是程序,而是程序運行時讀寫的數據,比如程序運行需要從中讀取數據文件,或者輸出內容的文件
以前所處理數據的輸入輸出都是以終端為對象的,即從終端的鍵盤輸入數據,運行結果顯示到顯示器上,其實有時候我們會把信息輸出到磁盤上,當需要的時候再從磁盤上把數據讀取到內存中使用,這里處理的就是磁盤上的文件
文件名
一個文件要有一個唯一的文件標識,以便用戶識別和引用
文件名包括3部分:文件路徑+文件名主干+文件后綴
文件的打開和關閉
緩沖文件系統中,關鍵的概念是==“文件類型指針”==,簡稱**“文件指針”**。
每個被使用的文件都在內存中開辟了一個相應的文件信息區,用來存放文件的相關信息(如文件的名字,文件狀態及文件當前的位置等)。==這些信息是保存在一個結構體變量中的。該結構體類型是由系統聲明的,取名FILE.==
1.不同的C編譯器的FILE類型包含的內容不完全相同,但是大同小異。
2.每當打開一個文件的時候,系統會根據文件的情況自動創建一個FILE結構的變量,并填充其中的信息,使用者不必關心細節。
3.一般都是通過一個FILE的指針來維護這個FILE結構的變量,這樣使用起來更加方便。
//我們可以創建一個FILE*的指針變量 FILE* pf;//文件指針變量
定義pf是一個指向FILE類型數據的指針變量。可以使pf指向某個文件的文件信息區(是一個結構體變量)。通過該文件信息區中的信息就能夠訪問該文件。也就是說,==通過文件指針變量能夠找到與它關聯的文件。==
文件在讀寫之前應該先==打開文件==,在使用結束之后應該==關閉文件==。
在編寫程序的時候,在打開文件的同時,都會返回一個FILE*的指針變量指向該文件,也相當于建立了指針和文件的關系。
ANSIC 規定使用==fopen函數來打開文件,fclose來關閉文件==
//打開文件 FILE* fopen(const char* filename,const char* mode); //關閉文件 int fclose(FILE* stream)
==我們主要用前三個==
#include int main() { //打開文件 FILE* pf = fopen("data.txt", "r"); if (pf == NULL) { printf("打開失敗.\n"); perror("fopen");//把錯誤信息打印到fopen:后面 return 0; } //讀文件 else { printf("打開成功\n"); //關閉文件 fclose(pf); pf = NULL; } return 0; }
==那就必須寫完整的文件名了==
看上面的打開方式可以知道==沒有文件會新建一個文件==,我們在桌面上試一下
#include int main() { //打開文件 FILE* pf = fopen("C:\Users\Administrator\Desktop\data.txt", "w"); if (pf == NULL) { printf("打開失敗.\n"); perror("fopen");//把錯誤信息打印到fopen:后面 return 0; } //寫文件 else { printf("打開成功\n"); //關閉文件 fclose(pf); pf = NULL; } return 0; }
假如已存在的文件里面有內容,w就是把文件里的內容全部銷毀了,變成一個空白文件
文件的順序讀寫
#include int main() { //打開文件 FILE* pf = fopen("C:\Users\Administrator\Desktop\data.txt", "w"); if (pf == NULL) { printf("打開失敗.\n"); perror("fopen");//把錯誤信息打印到fopen:后面 return 0; } //寫文件 else { fputc('b', pf); fputc('i', pf); fputc('t', pf); //關閉文件 fclose(pf); pf = NULL; } return 0; }
==那他適用所有輸出流是什么意思呢==
是因為他不僅僅可以打印到文件里面去,也可以打印到屏幕里面去
#include int main() { fputc('b', stdout); fputc('i', stdout); fputc('t', stdout); return 0; }
#include int main() { //打開文件 FILE* pf = fopen("C:\Users\Administrator\Desktop\data.txt", "r"); if (pf == NULL) { perror("fopen"); } else { //讀文件 int ch = fgetc(pf); printf("%c",ch); ch = fgetc(pf); printf("%c", ch); //關閉文件 fclose(pf); pf = NULL; } return 0; }
==同樣他適用所有輸入流==
#include int main() { int ch = fgetc(stdin); printf("%c\n", ch); ch = fgetc(stdin); printf("%c\n", ch); ch = fgetc(stdin); printf("%c\n", ch); return 0; }
==fputc(‘b’, stdout)這個函數等價于putchar(‘b’)函數==
==fgetc(stdin)這個函數等價于getchar函數==
#include int main() { //打開文件 FILE* pf = fopen("C:\Users\Administrator\Desktop\data.txt", "w"); if (pf == NULL) { perror("fopen"); return 0; } else { //寫一行數據 fputs("hello bit", pf); fputs("hello bit\n", pf); fputs("hello bit", pf); //關閉文件 fclose(pf); pf = NULL; } return 0; }
#include int main() { fputs("hello bit",stdout); fputs("hello bit\n",stdout); fputs("hello bit",stdout); return 0; }
#include int main() { //打開文件 FILE* pf = fopen("C:\Users\Administrator\Desktop\data.txt", "r"); if (pf == NULL) { perror("fopen"); return 0; } else { //讀一行數據 char arr[20] = { 0 }; fgets(arr, 5, pf); printf("%s\n",arr); fgets(arr, 5, pf); printf("%s\n", arr); //關閉文件 fclose(pf); pf = NULL; } return 0; }
#include int main() { char arr[20] = { 0 }; fgets(arr, 5, stdin); printf("%s\n", arr); fgets(arr, 5, stdin); printf("%s\n", arr); fgets(arr, 5, stdin); printf("%s\n", arr); return 0; }
#include struct MyStruct { int a; double b; }; int main() { struct MyStruct mystruct = { 20 ,3.14 }; //打開文件 FILE* pf = fopen("C:\Users\Administrator\Desktop\data.txt", "w"); if (pf == NULL) { perror("fopen"); return 0; } else { //寫數據 fprintf(pf, "%d %lf", mystruct.a, mystruct.b); //關閉文件 fclose(pf); pf = NULL; } return 0; }
#include struct S { int a; double b; char c; }; int main() { struct S s = { 10,3.25,'a' }; fprintf(stdout, "%d %lf %c", s.a, s.b, s.c); return 0; }
#include struct MyStruct { int a; double b; }; int main() { struct MyStruct mystruct = {0}; //打開文件 FILE* pf = fopen("C:\Users\Administrator\Desktop\data.txt", "r"); if (pf == NULL) { perror("fopen"); return 0; } else { //讀數據 fscanf(pf, "%d%lf", &(mystruct.a), &(mystruct.b)); printf("%d %lf", mystruct.a, mystruct.b); //關閉文件 fclose(pf); pf = NULL; } return 0; }
#include struct S { int a; double b; }; int main() { struct S s = { 0 }; fscanf(stdin, "%d%lf", &(s.a), &(s.b)); printf("%d %lf", s.a, s.b); return 0; }

#include struct MyStruct { int a; double b; char num[20]; }; int main() { struct MyStruct mystruct = {20,3.14,"zhuzhu"}; //打開文件 FILE* pf = fopen("C:\Users\Administrator\Desktop\data.txt", "wb"); if (pf == NULL) { perror("fopen"); return 0; } else { //寫文件--二進制的形式寫 fwrite(&mystruct, sizeof(struct MyStruct), 1, pf); //關閉文件 fclose(pf); pf = NULL; } return 0; }
#include struct MyStruct { int a; double b; char num[20]; }; int main() { struct MyStruct mystruct = {0}; //打開文件 FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\data.txt", "rb"); if (pf == NULL) { perror("fopen"); return 0; } else { //讀文件--二進制的形式讀 fread(&mystruct, sizeof(struct MyStruct), 1, pf); printf("%d %lf %s", mystruct.a, mystruct.b, mystruct.num); //關閉文件 fclose(pf); pf = NULL; } return 0; }
對比一組函數
#include struct MyStruct { int a; double b; char num[20]; }; int main() { char arr[20] = { 0 }; struct MyStruct mystruct = {20,3.14,"zhuzhu"}; struct MyStruct tmp = { 0 }; sprintf(arr, "%d %lf %s", mystruct.a, mystruct.b, mystruct.num); printf("%s",arr); sscanf(arr, "%d%lf%s", &(tmp.a), &(tmp.b), &(tmp.num)); printf("\n%d\n%lf\n%s\n", tmp.a, tmp.b, tmp.num); return 0; }
#include struct MyStruct { int a; double b; char num[20]; }; int main() { char arr[20] = { 0 }; struct MyStruct mystruct = {20,3.14,"zhuzhu"}; sprintf(arr, "%d %lf %s", mystruct.a, mystruct.b, mystruct.num); printf("%s",arr); return 0; }
文件的隨機讀寫
根據文件指針的位置和偏移量來定位文件指針。
#include int main() { //打開文件 FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\data.txt", "r"); if (pf == NULL) { perror("fopen"); return 0; } else { //隨機讀文件 //文件開頭向后偏移2 fseek(pf, 2, SEEK_SET); int ch = fgetc(pf); printf("%c\n",ch); //文件當前指針向前移2 fseek(pf, -2, SEEK_CUR); ch = fgetc(pf); printf("%c\n", ch); } return 0; }
根據文件指針的位置和偏移量來定位文件指針。
int a = ftell(pf); printf("%d\n", a);
讓文件指針的位置回到文件的起始位置
#include int main() { //打開文件 FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\data.txt", "r"); if (pf == NULL) { perror("fopen"); return 0; } else { //隨機讀文件 //文件開頭向后偏移2 fseek(pf, 2, SEEK_SET); int ch = fgetc(pf); printf("%c\n",ch); //文件當前指針向前移2 fseek(pf, -2, SEEK_CUR); ch = fgetc(pf); printf("%c\n", ch); int a = ftell(pf); printf("%d\n", a); rewind(pf); ch = fgetc(pf); printf("%c\n", ch); } return 0; }
文本文件和二進制文件
根據數據的組織形式,數據文件被稱為==文本文件==或者==二進制文件==。
數據在內存中以二進制的形式存儲,如果不加轉換的輸出到外存,就是==二進制文件==。
如果要求在外存上以ASCII碼的形式存儲,則需要在存儲前轉換。==以ASCII字符的形式存儲的文件就是文本文件==
字符一律以==ASCII形式存儲==,數值型數據既可以==用ASCII形式存儲,也可以使用二進制形式存儲。==
如有整數10000,如果以ASCII碼的形式輸出到磁盤,則磁盤中占用5個字節(每個字符一個字節),而二進制形式輸出,則在磁盤上只占4個字節(VS2013測試)。
我們把10000數據以二進制的形式寫到data文件中,并看一下
#include int main() { int a = 10000; FILE* pf = fopen("data.txt", "wb"); if (pf == NULL) { perror("fopen"); return 0; } else { //把a寫入 fwrite(&a, sizeof(int), 1, pf); } //關閉文件 fclose(pf); pf = NULL; return 0; }
文件讀取結束的判定
#include int main() { int ch = 0; FILE* pf = fopen("data.txt", "r"); if (pf == NULL) { perror("fopen"); return 0; } while ((ch = fgetc(pf))!=EOF) { printf("%c ", ch); } //關閉文件 fclose(pf); pf = NULL; return 0; }
feof 是文件讀取結束了,判斷是不是遇到文件末尾而結束的
ferror 文件讀取結束了,判斷是不是遇到錯誤后讀取結束
==牢記:在文件讀取過程中,不能用feof函數的返回值直接用來判斷文件的是否結束。而是應用于當文件讀取結束的時候,判斷是讀取失敗結束,還是遇到文件尾結束。==
文本文件讀取是否結束,判斷返回值是否為 EOF ( fgetc ),或者 NULL ( fgets )
例如:
fgetc 判斷是否為 EOF .
fgets 判斷返回值是否為 NULL .
二進制文件的讀取結束判斷,判斷返回值是否小于實際要讀的個數。
例如:
fread判斷返回值是否小于實際要讀的個數
文件緩沖區
ANSIC 標準采用“緩沖文件系統”處理的數據文件的,所謂緩沖文件系統是指系統自動地在內存中為程序中每一個正在使用的文件開辟一塊“文件緩沖區”。從內存向磁盤輸出數據會先送到內存中的緩沖區,裝滿緩沖區后才一起送到磁盤上。如果從磁盤向計算機讀入數據,則從磁盤文件中讀取數據輸入到內存緩沖區(充滿緩沖區),然后再從緩沖區逐個地將數據送到程序數據區(程序變量等)。緩沖區的大小根據C編譯系統決定的。
#include #include //VS2013 WIN10環境測試 int main() { FILE*pf = fopen("test.txt", "w"); fputs("abcdef", pf);//先將代碼放在輸出緩沖區 printf("睡眠10秒-已經寫數據了,打開test.txt文件,發現文件沒有內容\n"); Sleep(10000); printf("刷新緩沖區\n"); fflush(pf);//刷新緩沖區時,才將輸出緩沖區的數據寫到文件(磁盤) //注:fflush 在高版本的VS上不能使用了 printf("再睡眠10秒-此時,再次打開test.txt文件,文件有內容了\n"); Sleep(10000); fclose(pf); //注:fclose在關閉文件的時候,也會刷新緩沖區 pf = NULL; return 0; }
因為有緩沖區的存在,C語言在操作文件的時候,需要做刷新緩沖區或者在文件操作結束的時候關閉文件。
如果不做,可能導致讀寫文件的問題
==錢有價,代碼無價==
==我很希望來個01年中美黑客大戰,劍指美國,碼到成功,體現價值。==
C 語言 軟件開發
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。