http://www.csie.ntu.edu.tw/~cprog2003/downloads/Notes%20on%20C%20File%20I-O.htmFile I/O
The FILE type
- 當在C中想使用檔案時,就需要宣告FILE variable
- FILE variable是一個pointer,因它是一個指向檔案現在使用到哪裡的指標。 在比較底層的意義中(close to hardware),它是一個file descriptor。
在C中,實際上是使用Stream I/O的方式來存取資料。也就是說,當打開一個檔案後, OS那邊會將一部分的資料先讀起來在一個暫存的Buffer裡,然後FILE這個pointer就會去指向這個buffer, 每讀取一個字元時,它就會往前移動一個。同樣的,當我們在寫入的時候,當我們完成像是fprintf時, 它也是先寫入這個buffer中,直到這個buffer被flush或是寫出到device中,才會真正的做改變。
這張圖的左邊就是device;右邊就是buffer。
Associate the variable with a file
- Use fopen()
- Specify the file path and the mode
- 成功的話, fopen會return一個file pointer;否則, return NULL
"r" | open for reading; 假如檔案不存在,則失敗。 |
"w" | open or create for writing; 假如檔案存在,其現存的內容會被覆蓋。 |
"a" | open or create for writng; 看w的不同在於,它會接著現存的內容繼續做下去 |
"r+" | open for reading and writing; 檔案一定要存在 |
"w+" | open or create for reading and writing; 檔案不存在就開新檔案,存在就覆寫 |
"a+" | open or create for reading and writing; 不同處同上面a和w的差別 |
FILE *fopen(char *name, char *mode) |
Example:FILE *myfile;myfile = fopen("input.txt", "r");
|
Testing for EOF
- EOF是保留字,表示End Of File。
- 當想要檢查現在的file pointer是否已經只到檔案的結尾時,可以使用feof(file)
- 當真的已經是EOF時,return 0;否則,return non-zero
Syntax:int feof( FILE *stream );
|
Example: if( feof( myfile ) )
printf("End of file\n"); |
Writing / Reading by single character
- To read in or write out text by char, use fgetc() and fputc()
- fgetc會return下一個在input stream中的char,若是已經EOF,則return EOF。而為什麼他要return int而不是char,則是因為EOF已經不在char的範圍內(不在0~255,為-1)。
- fputc則會return所寫入的char的值;假如發生錯誤的話,return EOF。
Syntax:int fgetc( FILE *stream );int fputc( int c, FILE *stream );
|
Example:
FILE *myfile, *myfile2;
int c;
myfile = fopen("in", "r");>
myfile2 = fopen("out", "w");
while( (c=fgetc(myfile)) != EOF)
fputc(c, myfile2); |
Writing / Reading by line of text
- To read in or write out text by line, use fgets() and fputs()
- fgets會return指向str的char pointer;假若發生錯誤或是遇到EOF時,returns NULL
- fputs return 0 on success and EOF on error.
Syntax:char *fgets(char *str, int size, FILE *stream);int fputs(const char *str, FILE *stream);
|
Example:
FILE *myfile, *myfile2;
char tmp[80];
myfile = fopen("in", "r");>
myfile2 = fopen("out", "w");
while( (fgets(tmp, 80, myfile)) != NULL)
fputs(tmp, myfile2); |
fprintf() and fscanf()
- Work like printf and scanf, except with files
- 跟上面fgets, fputs不同的是,這兩個function可以做formatted I/O
Examples:fprintf(outputfile, "My age is %d\n", myAge);
fscanf(inputfile, "%f", &floatVariable);
|
Close the files
- 當在一個檔案的工作已經結束後,可以使用fclose(),使之前buffer的資料實際寫入。
- 因此當在對檔案的寫入結束後,最好還是用fclose將他關掉。
- 成功的話,return 0;否則,return EOF
Syntax:int fclose( FILE *stream );
|
A sample program
假如你們還是不會用的話 ,可以套用(參考)下面的程式。
#include
#define INFILE "input.txt"
//將下面這個學號換成你自己的學號
#define OUTFILE "R92922099"
char *readin(FILE *);
int main() {
FILE *infile, *outfile;
char *input;
/* 打開檔案 */
if( (infile = fopen(INFILE, "r")) == NULL ) {
printf("can't open input file\n");
exit(1); //假若失敗的話,就離開程式
}else if( (outfile = fopen(OUTFILE, "w")) == NULL ) {
printf("can't open output file\n");
exit(1); //假若失敗的話,就離開程式
}
/* 用剛剛取得的file pointer來讀取檔案的內容的動作 */
input = readin( infile );
/*
將你們如何處理從檔案中所讀到的資料result,
寫在這裡,或是在這裡呼叫function
*/
fclose(infile);
fclose(outfile);
}
//將檔案中所有的內容都讀取出來,用result指向這個資料,然後return這個pointer做處理
char *readin(FILE *in) {
char tmp[80];
char *result="";
while( fgets( tmp, 80, in)!=NULL ) {
asprintf(&result, "%s%s", result, tmp);
}
return result;
}
|