C 語言文件讀寫
在本教程中,您將學習如何在C語言中處理文件。您將通過示例學習在C語言中使用fprintf()、fscanf()、fread()、fwrite()、fseek()等處理標準I/O。
文件是計算機存儲設備中用于存儲數據的容器。
為什么需要文件?
- 當程序終止時,所有數據都會丟失。即使程序終止,存儲在文件中也會保留您的數據。
- 如果必須輸入大量數據,則將花費大量時間來全部輸入。
但是,如果您有一個包含所有數據的文件,則可以使用C中的一些命令方法輕松地訪問文件的內容。 - 您可以輕松地將數據從一臺計算機移動到另一臺計算機,而無需進行任何更改。
文件類型
處理文件時,您應該了解兩種類型的文件:
- 文本文件
- 二進制文件
1.文本文件
文本文件是普通的**.txt**文件。您可以使用任何簡單的文本編輯器(例如記事本)輕松創建文本文件。
打開這些文件時,您將以純文本形式看到文件中的所有內容。您可以輕松地編輯或刪除內容。
它們以最少的維護工作,易于閱讀,提供最少的安全性并占用更大的存儲空間。
2.二進制文件
二進制文件主要是計算機中的**.bin**文件。
它們不是以純文本格式存儲數據,而是以二進制格式(0和1)存儲數據。
與文本文件相比,它們可以容納更多數據,不易讀取,并提供更好的安全性。
文件操作
在C中,您可以對文件執行四個主要操作:
- 創建一個新文件
- 打開現有文件
- 關閉文件
- 讀取信息并將信息寫入文件
處理文件
處理文件時,需要聲明文件類型的指針。文件和程序之間的通信需要此聲明。
FILE *fptr;
打開文件-用于創建和編輯
使用stdio.h頭文件中定義的fopen()函數打開文件。
在標準I / O中打開文件的語法為:
ptr = fopen("fileopen","mode");
例如,
fopen("E:\\cprogram\\newprogram.txt","w");
fopen("E:\\cprogram\\oldprogram.bin","rb");
- 假設該文件newprogram.txt在路徑E:\cprogram中不存在。第一個函數創建一個名為newprogram.txt的新文件,并按照**‘w’**模式打開該文件進行寫入。
寫入模式允許您創建和編輯(覆蓋)文件的內容。 - 現在,假設第二個二進制文件oldprogram.bin存在于路徑E:\cprogram中。第二個函數打開現有文件,以二進制模式**‘rb’**讀取。
讀取模式僅允許您讀取文件,而不能寫入文件。
模式 | 模式的含義 | 文件不存在期間 |
---|---|---|
r | 以只讀方式打開。 | 如果文件不存在,則fopen()返回NULL。 |
rb | 打開以二進制模式讀取。 | 如果文件不存在,則fopen()返回NULL。 |
w | 打開文本文件,允許寫入文件。 | 打開一個文本文件,允許寫入文件。如果文件不存在,則會創建一個新文件。在這里,您的程序會從文件的開頭寫入內容。如果文件存在,則該會被截斷為零長度,重新寫入。 |
wb | 打開文件以二進制方式寫入。 | 如果文件存在,其內容將被覆蓋。 如果文件不存在,將創建它。 |
a | 打開進行追加。 數據添加到文件末尾。 | 如果文件不存在,將創建它。 |
ab | 打開以二進制方式追加。數據添加到文件末尾。 | 如果文件不存在,將創建它。 |
r+ | 開放供閱讀和寫作。 | 如果文件不存在,則fopen()返回NULL。 |
rb+ | 打開以二進制方式讀取和寫入。 | 如果文件不存在,則fopen()返回NULL。 |
w+ | 打開一個文本文件,允許讀寫文件 | 如果文件存在,其內容將被覆蓋。如果文件不存在,將創建它。 |
wb+ | 打開以二進制方式讀取和寫入。 | 如果文件存在,其內容將被覆蓋。 如果文件不存在,將創建它。 |
a+ | 打開以閱讀和追加。 | 如果該文件不存在,它將被創建。 |
ab+ | 打開以二進制模式讀取和追加。 | 如果文件不存在,將創建它。 |
關閉文件
讀取/寫入后,應關閉文件(文本文件和二進制文件)。
使用fclose()函數可以關閉文件。
fclose(fptr);
在這里,fptr是與要關閉的文件關聯的文件指針。
讀取和寫入文本文件
為了讀取和寫入文本文件,我們使用fprintf()和fscanf()函數。
它們只是printf()和scanf()的文件版本。 唯一的區別是fprint()和fscanf()需要指向結構FILE的指針。
示例1:寫入文本文件
#include <stdio.h>
#include <stdlib.h>int main()
{int num;FILE *fptr;// 如果您使用的是MacOS或Linux,請使用正確的路徑fptr = fopen("C:\\program.txt","w");if(fptr == NULL){printf("Error!"); exit(1); }printf("Enter num: ");scanf("%d",&num);fprintf(fptr,"%d",num);fclose(fptr);return 0;
}
該程序從用戶那里獲取一個號碼并將其存儲在文件中program.txt。
編譯并運行該程序后,您可以看到program.txt在計算機的C驅動器中創建的文本文件。打開文件時,您可以看到輸入的整數。
示例2:從文本文件讀取
#include <stdio.h>
#include <stdlib.h>int main()
{int num;FILE *fptr;if ((fptr = fopen("C:\\program.txt","r")) == NULL){printf("Error! opening file");//如果文件指針返回NULL,則程序退出。exit(1);}fscanf(fptr,"%d", &num);printf("Value of n=%d", num);fclose(fptr); return 0;
}
該程序讀取program.txt文件中存在的整數并將其打印到屏幕上。
如果您從示例1成功創建了文件,運行此程序將為您提供輸入的整數。
其他函數,如fgetchar(),fputc()等,可以以類似的方式使用。
讀寫二進制文件
在二進制文件的情況下,fread()和fwrite()函數用于分別讀取和寫入磁盤上的文件。
寫入二進制文件
要寫入二進制文件,需要使用fwrite()函數。這些函數采用四個參數:
- 要寫入磁盤的數據地址
- 要寫入磁盤的數據大小
- 此類數據的數量
- 指向要寫入的文件的指針。
fwrite(addressData, sizeData, numbersData, pointerToFile);
示例3:使用fwrite()寫入二進制文件
#include <stdio.h>
#include <stdlib.h>struct threeNum
{int n1, n2, n3;
};int main()
{int n;struct threeNum num;FILE *fptr;if ((fptr = fopen("C:\\program.bin","wb")) == NULL){printf("Error! opening file");// 如果文件指針返回NULL,則程序退出。exit(1);}for(n = 1; n < 5; ++n){num.n1 = n;num.n2 = 5*n;num.n3 = 5*n + 1;fwrite(&num, sizeof(struct threeNum), 1, fptr); }fclose(fptr); return 0;
}
在此程序中,我們在C驅動器中創建一個新文件program.bin。
我們聲明具有三個數字n1,n2和n3的結構體threeNum,并將其在主函數中定義為num。
現在,在for循環中,我們使用fwrite()將值存儲到文件中。
第一個參數接受num的地址,第二個參數接受結構threeNum的大小。
由于我們僅插入num的一個實例,因此第三個參數為1。最后一個參數* fptr指向我們要存儲數據的文件。
最后,我們關閉文件。
從二進制文件讀取
fread()函數也采用與上述fwrite()函數相似的4個參數。
fread(addressData, sizeData, numbersData, pointerToFile);
示例4:使用fread()從二進制文件讀取
#include <stdio.h>
#include <stdlib.h>struct threeNum
{int n1, n2, n3;
};int main()
{int n;struct threeNum num;FILE *fptr;if ((fptr = fopen("C:\\program.bin","rb")) == NULL){printf("Error! opening file");//如果文件指針返回NULL,則程序退出。exit(1);}for(n = 1; n < 5; ++n){fread(&num, sizeof(struct threeNum), 1, fptr); printf("n1: %d\tn2: %d\tn3: %d", num.n1, num.n2, num.n3);}fclose(fptr); return 0;
}
在此程序中,您讀取相同的文件program.bin,并逐個循環瀏覽記錄。
簡單來說,您將從* fptr指向的文件中讀取一個threeNum大小的threeNum*fptrnum記錄到num結構中。
您將獲得與示例3中插入的記錄相同的記錄。
使用fseek()獲取數據
如果文件中有很多記錄,并且需要訪問特定位置的記錄,則需要遍歷所有記錄才能獲取該記錄。
這將浪費大量的內存和操作時間。使用fseek()可以輕松獲得所需數據。
顧名思義,fseek()將光標定位到文件中的給定記錄。
fseek()的語法
fseek(FILE * stream, long int offset, int whence);
第一個參數流是指向文件的指針。第二個參數是要查找的記錄的位置,第三個參數指定偏移量開始的位置。
位置 | 含義 |
---|---|
SEEK_SET | 從文件開頭開始偏移。 |
SEEK_END | 從文件的末尾開始偏移。 |
SEEK_CUR | 從文件中光標的當前位置開始偏移。 |
示例5:fseek()
#include <stdio.h>
#include <stdlib.h>struct threeNum
{int n1, n2, n3;
};int main()
{int n;struct threeNum num;FILE *fptr;if ((fptr = fopen("C:\\program.bin","rb")) == NULL){printf("Error! opening file");//如果文件指針返回NULL,則程序退出。exit(1);}// 將光標移到文件末尾fseek(fptr, -sizeof(struct threeNum), SEEK_END);for(n = 1; n < 5; ++n){fread(&num, sizeof(struct threeNum), 1, fptr); printf("n1: %d\tn2: %d\tn3: %d\n", num.n1, num.n2, num.n3);cfseek(fptr, -2*sizeof(struct threeNum), SEEK_CUR);}fclose(fptr); return 0;
}
該程序將以相反的順序(從最后到第一)開始從文件program.bin中讀取記錄并進行打印。