使用檔案方式
含義
"r"(隻讀)
為輸入打開一個文本檔案
"w"(隻寫)
為輸出打開一個文本檔案
"a"(追加)
為追加打開一個文本檔案
"rb"(隻讀)
為輸入打開一個二進制檔案
"wb"(隻寫)
為輸出打開一個二進制檔案
"ab"(追加)
為追加打開一個二進制檔案
"r+"(讀寫)
為讀/寫打開一個文本檔案
"w+"(讀寫)
為讀/寫建立一個文本檔案
"a+"(讀寫)
為讀/寫打開一個文本檔案
"rb+"(讀寫)
為讀/寫打開一個二進制檔案
"wb+"(讀寫)
為讀/寫建立一個二進制檔案
"ab+"(讀寫)
為讀/寫打開一個二進制檔案
說明: 1. 使用"r"時,如果檔案不存在,則出錯。
2. 使用"w"時,如果沒有檔案,則建立一個新檔案。
3. 使用"a"時,如果希望向檔案尾添加資料,則該檔案必須存在,否則出錯。
4. "r+","w+","a+"都是可以輸入和輸出資料,但必須遵守上述3點
5. 操作二進制檔案時,加上"b"字元,且二進制檔案對換行符不會進行轉換,而文本檔案會将換行符轉換為回車和換行兩個字元。
檔案的關閉(fclose函數)
在使用完一個檔案後,若不關閉則會造成系統資源洩漏。使用fclose()關閉檔案即可,原型為 int fclose(FILE* fp)。使用:fclose(fp); flose()傳回0時為順利關閉檔案,否則傳回EOF(-1)。
檔案的讀寫1) fputc(), fgetc()分别為從檔案流中寫和讀一個字元,原型分别如下:
寫:int fputc(int c, FILE* fp); 讀:int fgetc(FILE* fp); 失敗時均傳回EOF
2) fputs(), fgets()分别為從檔案流中寫和讀一個字元串,原型分别如下:
寫:int fputs(const char* str, FILE* fp); 例如: fputs("I love this game!", fp);
讀:char* fgets(char* str, int n, FILE* fp); 從流中讀取n-1個字元或讀完一行,參數str用于接收讀取的字元串。注意當讀取一行時,不包括行尾的'\n'字元。
3) fseek() 一般用于二進制模式打開的檔案中,功能是定位到流中指定的位置。原型如下:
int fseek(FILE* fp, lont offset, int whence); 參數offset是移動的字元數,whence是移動的基準,取值是:
SEEK_SET 0 //檔案開頭
SEEK_CUR 1 //目前讀寫的位置
SEEK_END 2 //檔案尾部
4) fprintf(),fscanf()是将資料按格式輸出輸入到檔案流中,用法類似printf()和scanf()。原型分别如下:
int fprintf(FILE* fp, const char* format, ...); 它與printf()不同的就是将資料寫到了檔案流中,而不是控制台罷了。
int fscanf(FILE* fp, cosnt char* format, ...); 從檔案流中按格式讀取,與scanf()不同的就是資料是從檔案流中讀取而已。
例如: fprintf(fp, "count=%d", 5); fscanf(fp, "%d", &x);
5) feof()是檢測是否已到檔案尾,是傳回真,否則傳回0,原型是 int feof(FILE* fp);
6) rewind() 則是把目前的讀寫位置回到檔案開始,相當于 fseek(fp, 0L, SEEK_SET); 原型: void rewind(FILE* fp);
7) remove() 删除檔案,原型: int remove(const char* filename); 參數為要删除的檔案名,成功則傳回0;
8) fread(), fwrite() 它們相當于可将一塊的資料讀出或寫入,相當的友善。原型如下:
size_t fread(void* ptr, size_t size, size_t n, FILE* fp); 從流中讀指定個數的字元,size是每塊的位元組婁,n則是讀取的塊數。
size_t fwrite(const void* ptr, size_t size, size_t n, FILE* fp); 類似的是向檔案流中寫入n塊size位元組數的資料。可以看到資料指針為void*型,即可以使用任何類型的指針來替換。例如:
現在一個結構體: struct student_t{char name[16]; int id; int age;}; 建立三個學生的資料并指派:struct student_t stu[3];
這時,當我們找開檔案後(一般是進制模式),可以調用fwrite()将三個學生的資料都寫入到檔案中,兩種方式:
for(int i = 0; i < 3; ++i)
fwrite(&stu[i], sizeof(struct student_t), 1, fp);
或者:fwrite(stu, sizeof(struct student_t), 3, fp);
些時,我們調用fread()函數便可很輕松的将剛才寫入的3個學生的資料讀取出來:
struct student_t stus[3];
for(int i = 0; i < 3; ++i)
fread(&stus[i], sizeof(struct student_t), 1, fp);
或者:fread(stus, sizeof(struct student_t), 3, fp); 這樣便可将三個學生的資料讀入到stus變量中了(有木有很友善呐)
注意:如果你發現使用fread()讀取之後,最後一個學生讀取的資料不完全,可能是由于你沒有使用二進制模式打開的原因。
9) 最後是tmpfile()和tmpnam(),前者為生成一個臨時檔案,後者為生成一個唯一的檔案名,具體使用在此不介紹了。
二、使用C++中的fstream檔案流操作類進行檔案的讀寫
使用fstream操作檔案與使用C庫函數類似,隻不過fstream為面向對象方式,或多了上些C++的特性。首先,這裡大概有三個流:
fstream為檔案輸入輸出流,ifstream為輸入檔案流,ofstream為輸出檔案流,它們與ostream不同的就流的目的地為檔案,而不是控制台。這裡隻介紹與上述的一些不同點:
1. 打開檔案,如可以是 ifstream input_file("file2.txt"); 這樣将會以預設方式打開file2.txt檔案并進行讀取。也可使用open()方式打開一個檔案,并指定打開方式,例如:
ifstream input_file;
input_file.open("file2.txt", ios::binary);
打開後,可以使用is_open()檢測是否打開成功:
if(input_file.is_open()){},然後可以使用流操作符向檔案寫資料了,例如:
input_file << "this is a test line";
input_file << "another info";
另外,這裡的檔案打開方式在ios空間下:
ios::app 添加到檔案尾
ios::ate 把檔案标志放在末尾而非起始。
ios::trunc 預設. 截斷并覆寫檔案。
ios::nocreate 檔案不存在也不建立。
ios::noreplace 檔案存在則失敗。
ofstream使用方式類似,讀取一行資料可以使用getline(buf, count), 類型于fgets()。fstream類還提供一個很多其它方法,如fclose()為關閉檔案,eof()用于檢測狀态是否已經到了檔案末尾。
這裡還有兩個類似于上述的fread()和fwrite()函數,是read(), write(),功能和用法類似類似,例如:
output_file.write((const char*)stu, 3 * sizeof(struct student_t));
input_file.read((char*)stus, 3 * sizeof(struct student_t));
注意,這裡也需要使用二進制模式打開,否則read的時候最後的上些資料讀不完全。調用上面兩個函數後可以使用bad()來檢測檔案流對象是否錯誤,例如,if(input_file.bad()){printf("error when read file\n"); return;},最後input_file.close()即可。
最後,C/C++檔案的操作并不複雜,多使用幾次便可熟練掌握,需要注意的就是檔案的打開方式,和當用同一個檔案指針進行又讀又寫時,注意檔案指針位置的移動。