C File System
檔案指標 C語言提供了許多檔案處理的函式 需要搭配一個資料型態為FILE的指標來使用 檔案指標指向一個含有檔案資訊的結構 包括資訊 緩衝區的位置 緩衡區內現在字元的位置 目前檔案正在被讀取、寫入或檔案結束
檔案指標 使用者不需知道檔案指標的細節,所有定義可由<stdio.h>獲得 FILE *fp; 就像printf()我們只需include而不需寫定義一樣 FILE *fp; fp是一個指標指向FILE FILE就像int只是一個型別名稱 在<stdio.h>中用typedef定義,而不是一個結構標籤
C函式庫中已經宣告好3個FILE *的指標,分別是stdin、stdout、stderr printf("...")事實上是呼叫fprintf( stdout, "....") scanf("...")事實上是呼叫fscanf( stdin, "..." ) fprintf( stderr, "....")所印在螢幕上的東西不會被輸出轉向所影響
檔案格式 C可以建立兩種格式的檔案 用途 文字檔案格式(text file) 二元檔案格式(binary file) 將資料轉換成字元的格式存入檔案 存放的東西都是可視的英文字母或數字符號等 二元檔案格式(binary file) 將數值的內容使用二進位方式直接存入檔案中 用途 文字檔格式通常用來列印報表,或是讀入人為製作的檔案 二元檔案處理速度快、佔的空間小
檔案處理流程
開啟與關閉檔案 fopen 開啟檔案 fclose 關閉檔案
fopen 程式中叫用的方法如: 第一個參數是字串,指出檔案名稱, 第二個參數是模式,也是一個字串 模式有r、w、a三種: fp = fopen(name, mode); 第一個參數是字串,指出檔案名稱, 第二個參數是模式,也是一個字串 模式有r、w、a三種: r :唯讀模式(read) w :寫入模式(write) a :增加模式(append),從檔案最後面繼續寫入資料 如果希望同時讀寫檔案,可以在模式字串後加上+ r+ , w+, a+
以二元模式開啟檔案 可以在模式字串加b 打開一個不存在的檔案來寫入或附加在檔案尾端 打開一個存在的檔案寫入時,舊的檔案內容會被刪除 rb:代表以唯讀模式即二元檔案格式開啟 打開一個不存在的檔案來寫入或附加在檔案尾端 檔案必須儘可能先被建立 打開一個存在的檔案寫入時,舊的檔案內容會被刪除 若是增加模式(a)就會保留它們,並寫入到檔案尾端 嘗試讀一個不存在的檔案會造成錯誤,或是讀取一個不被允許讀取的檔案也會產生錯誤 如有錯誤產生, fopen 會傳回NULL
fclose : 關閉該檔案 fclose(FILE *fp); 檔案不用時,需隨手關閉該檔案 關閉檔案時會強迫仍在電腦緩衝區的所有資料輸出到檔案裡
範例練習:製作及開啟檔案
範例練習:讀/寫檔案 寫入檔案 fprintf(FILE *p, ...) 除了前面加個檔案指標外,其餘與printf()一樣
讀取資料: fscanf() fscanf(FILE *p, ...) 除了前面加個檔案指標外,其餘與scanf()一樣 注意:通常fprintf()和fscanf()都是用來處理文字格式檔案
讀取二元檔: fread() fread(pointer to variable, item size, item number, FILE *fp) pointer to variable 是一個指向存放資料記憶體的指標 item size是資料型態的大小 item number是讀入的個數 fp是指向檔案的指標 從fp所指到的檔案讀一個整數(4 bytes)到num所指的記憶體 int num; fread(&num, sizeof(int), 1, fp); 從fp所指到的檔案讀一個字串(10 bytes)到str所指的記憶體 char str[10]; fread(str, sizeof(str), 1, fp);
寫入二元檔: fwrite() fwrite(pointer to variable, item size, item number, FILE *fp) 從num所指的位址寫一個整數(4 bytes)到fp所指的檔案之中 fwrite(&num, sizeof(int), 1, fp); 注意 通常fread()和fwrite()都是用來處理二元格式檔案
使用 fget fgetc(FILE *fp) 從fp所指的檔案讀入一個字元。 printf("We read a character %c from the file.\n", fgetc(fp)); fputc(int c, FILE *fp) 將字元c寫入fp所指的檔案。 scanf("%c",&ch); fputc(ch, fp);
使用 fput fgets(char *buffer, int max_char_num, FILE *fp) 從fp所指到的檔案讀入一個字串到buffer,最多只允許max_char_num-1個字元 與gets()不同的是,fgets()函式會保留換行字元 fputs(const char *str, FILE *fp) 將str這個字串的內容寫到fp所指的檔案裡面 與puts()不同的是,fputs()不會自動加上換行字元
其他檔案處理函數 feof(FILE *fp) 用來判斷檔案游標是否已經到了檔案的結尾 if(feof(fp)) printf("We reach the end-of-file.\n");
補充說明 寫法一 while(!feof(fin)){ fscanf(fin,”%s”,line); printf(“%s\n”,line); } 適用情況(結尾沒空白or換行) 不適用(結尾有空白or換行) 1 2 3 J A C EOF 1 2 3 J A C \n EOF
補充說明 寫法二 while(1){ fscanf(fin,”%s”,line); if(feof(fin))break; printf(“%s\n”,line); } 不適用情況(結尾沒空白or換行) 適用(結尾有空白or換行) 1 2 3 J A C EOF 1 2 3 J A C \n EOF ↓
其他檔案處理函數 ferror(FILE *fp) 用來判斷檔案讀寫是否出現問題 if(ferror(fp)) printf("We encounter file access error.\n"); rewind(FILE *fp) 將檔案游標重設到檔案的開頭,並將錯誤旗標(flag)重設
其他檔案處理函數 fseek(FILE *fp, how man bytes to move, where to start) SEEK_SET 表示從檔案開頭起算 SEEK_CUR 表示目前游標位置起算 SEEK_END 表示從檔案結尾起算 how many bytes 正值表示往檔案結尾移動,負值表示往開頭 fseek(fp,0,SEEK_SET); //跟rewind一樣移到檔案開頭 fseek(fp,1,SEEK_CUR); //檔案指標向後移動一個byte
檔案游標移動範例
檔案處理函數原型和回傳值 FILE fopen(const char *,const char *) 成功傳回檔案指標,失敗傳回NULL int fclose(FILE *) 成功傳回0,失敗傳回EOF int fprintf(FILE *, const char *, ...) 傳回寫出字元個數,失敗傳回EOF int fscanf(FILE *, const char *, ...) 傳回讀入字元個數,失敗傳回EOF int fread(void *, size_t, sizet, FILE *) 傳回讀入項目個數 int fwrite(void *, size_t, sizet, FILE *) 傳回寫出項目個數 int fseek(FILE *, int, int) 成功傳回0,失敗傳回非0值 void rewind(FILE *) int feof(FILE *) 已到檔尾傳回非零值,否則傳回0 int ferror(FILE *) 發生錯誤傳回非零值,否則傳回0 void perror(const char *)
強制終止檔案處理: exit() 被叫用時,程式終止執行 參數由程式自行設定 if( (fp=fopen(fname,"r")) == NULL ) { printf("The file doesn't exist.\n"); exit(0); } 參數由程式自行設定 一般來說傳入的值是 0 則通知執行成功 非零則表示有不正常的情況 exit會對每個打開的輸出檔案叫用 fclose,強迫清光任何一個緩衝區