在本教程中,您將學(xué)習(xí)如何在C語言中處理文件。您將通過示例學(xué)習(xí)在C語言中使用fprintf()、fscanf()、fread()、fwrite()、fseek()等處理標(biāo)準(zhǔn)I/O。
文件是計(jì)算機(jī)存儲設(shè)備中用于存儲數(shù)據(jù)的容器。
當(dāng)程序終止時(shí),所有數(shù)據(jù)都會(huì)丟失。即使程序終止,存儲在文件中也會(huì)保留您的數(shù)據(jù)。
如果必須輸入大量數(shù)據(jù),則將花費(fèi)大量時(shí)間來全部輸入。
但是,如果您有一個(gè)包含所有數(shù)據(jù)的文件,則可以使用C中的一些命令方法輕松地訪問文件的內(nèi)容。
您可以輕松地將數(shù)據(jù)從一臺計(jì)算機(jī)移動(dòng)到另一臺計(jì)算機(jī),而無需進(jìn)行任何更改。
處理文件時(shí),您應(yīng)該了解兩種類型的文件:
文本文件
二進(jìn)制文件
文本文件是普通的.txt文件。您可以使用任何簡單的文本編輯器(例如記事本)輕松創(chuàng)建文本文件。
打開這些文件時(shí),您將以純文本形式看到文件中的所有內(nèi)容。您可以輕松地編輯或刪除內(nèi)容。
它們以最少的維護(hù)工作,易于閱讀,提供最少的安全性并占用更大的存儲空間。
二進(jìn)制文件主要是計(jì)算機(jī)中的.bin文件。
它們不是以純文本格式存儲數(shù)據(jù),而是以二進(jìn)制格式(0和1)存儲數(shù)據(jù)。
與文本文件相比,它們可以容納更多數(shù)據(jù),不易讀取,并提供更好的安全性。
在C中,您可以對文件執(zhí)行四個(gè)主要操作:
創(chuàng)建一個(gè)新文件
打開現(xiàn)有文件
關(guān)閉文件
讀取信息并將信息寫入文件
處理文件時(shí),需要聲明文件類型的指針。文件和程序之間的通信需要此聲明。
FILE *fptr;
使用stdio.h頭文件中定義的fopen()函數(shù)打開文件。
在標(biāo)準(zhǔn)I / O中打開文件的語法為:
ptr = fopen("fileopen","mode");
例如,
fopen("E:\\cprogram\\newprogram.txt","w"); fopen("E:\\cprogram\\oldprogram.bin","rb");
假設(shè)該文件newprogram.txt在路徑E:\cprogram中不存在。第一個(gè)函數(shù)創(chuàng)建一個(gè)名為newprogram.txt的新文件,并按照'w'模式打開該文件進(jìn)行寫入。
寫入模式允許您創(chuàng)建和編輯(覆蓋)文件的內(nèi)容。
現(xiàn)在,假設(shè)第二個(gè)二進(jìn)制文件oldprogram.bin存在于路徑E:\cprogram中。第二個(gè)函數(shù)打開現(xiàn)有文件,以二進(jìn)制模式'rb'讀取。
讀取模式僅允許您讀取文件,而不能寫入文件。
模式 | 模式的含義 | 文件不存在期間 |
---|---|---|
r | 以只讀方式打開。 | 如果文件不存在,則fopen()返回NULL。 |
rb | 打開以二進(jìn)制模式讀取。 | 如果文件不存在,則fopen()返回NULL。 |
w | 打開文本文件,允許寫入文件。 | 打開一個(gè)文本文件,允許寫入文件。如果文件不存在,則會(huì)創(chuàng)建一個(gè)新文件。 在這里,您的程序會(huì)從文件的開頭寫入內(nèi)容。 如果文件存在,則該會(huì)被截?cái)酁榱汩L度,重新寫入。 |
wb | 打開文件以二進(jìn)制方式寫入。 | 如果文件存在,其內(nèi)容將被覆蓋。 如果文件不存在,將創(chuàng)建它。 |
a | 打開進(jìn)行追加。 數(shù)據(jù)添加到文件末尾。 | 如果文件不存在,將創(chuàng)建它。 |
ab | 打開以二進(jìn)制方式追加。 數(shù)據(jù)添加到文件末尾。 | 如果文件不存在,將創(chuàng)建它。 |
r+ | 開放供閱讀和寫作。 | 如果文件不存在,則fopen()返回NULL。 |
rb+ | 打開以二進(jìn)制方式讀取和寫入。 | 如果文件不存在,則fopen()返回NULL。 |
w+ | 打開一個(gè)文本文件,允許讀寫文件 | 如果文件存在,其內(nèi)容將被覆蓋。 如果文件不存在,將創(chuàng)建它。 |
wb+ | 打開以二進(jìn)制方式讀取和寫入。 | 如果文件存在,其內(nèi)容將被覆蓋。 如果文件不存在,將創(chuàng)建它。 |
a+ | 打開以閱讀和追加。 | 如果該文件不存在,它將被創(chuàng)建。 |
ab+ | 打開以二進(jìn)制模式讀取和追加。 | 如果文件不存在,將創(chuàng)建它。 |
讀取/寫入后,應(yīng)關(guān)閉文件(文本文件和二進(jìn)制文件)。
使用fclose()函數(shù)可以關(guān)閉文件。
fclose(fptr);
在這里,fptr是與要關(guān)閉的文件關(guān)聯(lián)的文件指針。
為了讀取和寫入文本文件,我們使用fprintf()和fscanf()函數(shù)。
它們只是printf()和scanf()的文件版本。 唯一的區(qū)別是fprint()和fscanf()需要指向結(jié)構(gòu)FILE的指針。
#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; }
該程序從用戶那里獲取一個(gè)號碼并將其存儲在文件中program.txt。
編譯并運(yùn)行該程序后,您可以看到program.txt在計(jì)算機(jī)的C驅(qū)動(dòng)器中創(chuàng)建的文本文件。打開文件時(shí),您可以看到輸入的整數(shù)。
#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文件中存在的整數(shù)并將其打印到屏幕上。
如果您從示例1成功創(chuàng)建了文件,運(yùn)行此程序?qū)槟峁┹斎氲恼麛?shù)。
其他函數(shù),如fgetchar(),fputc()等,可以以類似的方式使用。
在二進(jìn)制文件的情況下,fread()和fwrite()函數(shù)用于分別讀取和寫入磁盤上的文件。
要寫入二進(jìn)制文件,需要使用fwrite()函數(shù)。這些函數(shù)采用四個(gè)參數(shù):
要寫入磁盤的數(shù)據(jù)地址
要寫入磁盤的數(shù)據(jù)大小
此類數(shù)據(jù)的數(shù)量
指向要寫入的文件的指針。
fwrite(addressData, sizeData, numbersData, pointerToFile);
#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驅(qū)動(dòng)器中創(chuàng)建一個(gè)新文件program.bin。
我們聲明具有三個(gè)數(shù)字n1,n2和n3的結(jié)構(gòu)體threeNum,并將其在主函數(shù)中定義為num。
現(xiàn)在,在for循環(huán)中,我們使用fwrite()將值存儲到文件中。
第一個(gè)參數(shù)接受num的地址,第二個(gè)參數(shù)接受結(jié)構(gòu)threeNum的大小。
由于我們僅插入num的一個(gè)實(shí)例,因此第三個(gè)參數(shù)為1。最后一個(gè)參數(shù)* fptr指向我們要存儲數(shù)據(jù)的文件。
最后,我們關(guān)閉文件。
fread()函數(shù)也采用與上述fwrite()函數(shù)相似的4個(gè)參數(shù)。
fread(addressData, sizeData, numbersData, pointerToFile);
#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,并逐個(gè)循環(huán)瀏覽記錄。
簡單來說,您將從* fptr指向的文件中讀取一個(gè)threeNum大小的threeNum*fptrnum記錄到num結(jié)構(gòu)中。
您將獲得與示例3中插入的記錄相同的記錄。
如果文件中有很多記錄,并且需要訪問特定位置的記錄,則需要遍歷所有記錄才能獲取該記錄。
這將浪費(fèi)大量的內(nèi)存和操作時(shí)間。使用fseek()可以輕松獲得所需數(shù)據(jù)。
顧名思義,fseek()將光標(biāo)定位到文件中的給定記錄。
fseek(FILE * stream, long int offset, int whence);
第一個(gè)參數(shù)流是指向文件的指針。第二個(gè)參數(shù)是要查找的記錄的位置,第三個(gè)參數(shù)指定偏移量開始的位置。
位置 | 含義 |
---|---|
SEEK_SET | 從文件開頭開始偏移。 |
SEEK_END | 從文件的末尾開始偏移。 |
SEEK_CUR | 從文件中光標(biāo)的當(dāng)前位置開始偏移。 |
#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); } // 將光標(biāo)移到文件末尾 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); fseek(fptr, -2*sizeof(struct threeNum), SEEK_CUR); } fclose(fptr); return 0; }
該程序?qū)⒁韵喾吹捻樞颍◤淖詈蟮降谝唬╅_始從文件program.bin中讀取記錄并進(jìn)行打印。