C语言—文件基础
目錄
- 文件概述
- 文件的定義
- 文件的分類
- 文件類型指針
- 文件函數(shù)
- 文件的打開(fopen函數(shù))
- 文件的關(guān)閉(fclose函數(shù))
- 當(dāng)前活動指針(ftell 函數(shù))
- rewind()函數(shù)
- 設(shè)置當(dāng)前位置(fseek 函數(shù))
- 字符輸入輸出函數(shù)(fputc()和fgetc())
- fwrite()函數(shù)
- fread()函數(shù)
- 格式化讀寫函數(shù)(fprintf()和fscanf())
- putw()和getw()
- fgets函數(shù)
- fputs函數(shù)
- ferror函數(shù)(出錯的檢測)
- clearerr函數(shù)(出錯的檢測)
文件概述
文件的定義
所謂文件一般指存儲在外部介質(zhì)(如磁盤磁帶)上數(shù)據(jù)的集合.
操作系統(tǒng)是以文件為單位對數(shù)據(jù)進(jìn)行管理的.
文件的分類
①從操作系統(tǒng)的角度看,每一個與主機(jī)相連的輸入輸出設(shè)備看作是一個文件。
例:輸入文件:終端鍵盤
輸出文件:顯示屏和打印機(jī)
②從用戶觀點:
特殊文件(標(biāo)準(zhǔn)輸入輸出文件或標(biāo)準(zhǔn)設(shè)備文件)
普通文件(磁盤文件)
③按數(shù)據(jù)的組織形式:
ASCII文件(文本文件):每一個字節(jié)放一個ASCII代碼二進(jìn)制文件:把內(nèi)存中的數(shù)據(jù)按其在內(nèi)存中的存儲形式原樣輸出到磁盤上存放.
例:整數(shù)10000在內(nèi)存中的存儲形式以及分別按ASCII碼形式和二進(jìn)制形式輸出如下圖所示:
ASCII文件和二進(jìn)制文件的比較:
1、ASCII文件便于對字符進(jìn)行逐個處理,也便于輸出字符。但一般占存儲空間較多,而且要花費轉(zhuǎn)換時間。
2、二進(jìn)制文件可以節(jié)省外存空間和轉(zhuǎn)換時間,但一個字節(jié)并不對應(yīng)一個字符,不能直接輸出字符形式。
3、一般中間結(jié)果數(shù)據(jù)需要暫時保存在外存上,以后又需要輸入內(nèi)存的,常用二進(jìn)制文件保存。
④文件的處理方法:
緩沖文件系統(tǒng):系統(tǒng)自動地在內(nèi)存區(qū)為每一個正在使用的文件開辟一個緩沖區(qū)。用緩沖文件系統(tǒng)進(jìn)行的輸入輸出又稱為高級磁盤輸入輸出。
非緩沖文件系統(tǒng):系統(tǒng)不自動開辟確定大小的緩沖區(qū),而由程序為每個文件設(shè)定緩沖區(qū)。用非緩沖文件系統(tǒng)進(jìn)行的輸入輸出又稱為低級輸入輸出系統(tǒng)。
文件類型指針
在緩沖文件系統(tǒng)中,每個被使用的文件都要在內(nèi)存中開辟一FILE類型的區(qū),存放文件的有關(guān)信息。stdio.h 中定義了一個稱為 FILE 的結(jié)構(gòu).
文件指針?biāo)璧奈ㄒ宦暶鳛?#xff1a;FILE *fp;
文件指針指向一個結(jié)構(gòu),該結(jié)構(gòu)包含以下信息:文件名、文件的當(dāng)前位置、文件是否正在讀或?qū)?、是否出錯或是否到達(dá)文件末尾
文件緩沖區(qū)示意圖:
文件操作基本流程:
文件函數(shù)
| 打開文件 | fopen() | 打開文件 |
| 關(guān)閉文件 | fclose() | 關(guān)閉文件 |
| 文件定位 | fseek() | 改變文件位置指針的位置 |
| Rewind() | 使文件位置指針重新至于文件開頭 | |
| Ftell() | 返回文件位置指針的當(dāng)前值 | |
| 文件狀態(tài) | feof() | 若到文件末尾,函數(shù)值為真 |
| ferror() | 若對文件操作出錯,函數(shù)值為真 | |
| clearerr() | 使ferror和feof()函數(shù)值置零 |
文件的打開(fopen函數(shù))
函數(shù)調(diào)用:
FILE *fp; fp=fopen(文件名,使用文件方式);①需要打開的文件名,也就是準(zhǔn)備訪問的文件的名字;
②使用文件的方式(“讀”還是“寫”等);
③讓哪一個指針變量指向被打開的文件。
文件的打開與關(guān)閉:
“r” (只讀)為輸入,打開一個文本文件
“w” (只寫)為輸出,打開一個文本文件
“a” (追加)向文本,文件尾增加數(shù)據(jù)
“rb” (只讀)為輸入,打開一個二進(jìn)制文件
“wb” (只寫)為輸出,打開一個二進(jìn)制文件
"ab“ (追加)向二進(jìn)制文件尾增加數(shù)據(jù)
"r+“ (讀寫)為讀/寫打開一個文本文件
"w+” (讀寫)為讀/寫建立一個新的文本文件
“a+” (讀寫)為讀/寫打開一個文本文件(追加)
"rb+“ (讀寫)為讀/寫打開一個二進(jìn)制文件
“wb+“ (讀寫)為讀/寫建立一個新的二進(jìn)制文件
“ab+” (讀寫)為讀/寫打開一個二進(jìn)制文件
“r+” 與"w+"兩種方式打開的區(qū)別?
當(dāng)?shù)谝淮未蜷_一個文件時,文件不存在,則需要對文件進(jìn)行創(chuàng)建(程序創(chuàng)建,不是人工手動創(chuàng)建),如果用r+這種模式open的話會返回失敗,如果用w+,當(dāng)?shù)诙未蜷_這個文件時就會重新創(chuàng)建一個新的文件,那么原來文件里的數(shù)據(jù)就會丟失。
文件的關(guān)閉(fclose函數(shù))
函數(shù)調(diào)用:
fclose(文件指針);
函數(shù)功能:
使文件指針變量不指向該文件,也就是文件指針變量與文件“脫鉤”,此后不能再通過該指針對原來與其相聯(lián)系的文件進(jìn)行讀寫操作
返回值:
關(guān)閉成功返回值為0;否則返回EOF(-1)
當(dāng)前活動指針(ftell 函數(shù))
FILE 結(jié)構(gòu)提供了一個指針,用以跟蹤發(fā)生 I/O 操作的位置,每當(dāng)從流中讀取或?qū)懭胍粋€字符,當(dāng)前活動指針(即 curp)就會向前移動,當(dāng)前活動指針的當(dāng)前位置可以借助 ftell() 函數(shù)來獲得。
函數(shù)原型:long int ftell(FILE *fp);
返回值:成功時返回文件指針位置,否則返回-1
rewind()函數(shù)
功能說明:將文件位置指示器置于文件開頭相當(dāng)于reset(重置)文件指針
函數(shù)原型:void rewind(FILE * fp) ;
設(shè)置當(dāng)前位置(fseek 函數(shù))
功能說明:通過指定相對于開始位置、當(dāng)前位置或流的末尾位置的字節(jié)數(shù)來重定位 curp,這取決于 fseek() 函數(shù)中指定的位置
函數(shù)原型:int fseek (FILE *fp, long int offset, int origin);
參數(shù):
fp:需設(shè)置的文件指針
offset:偏移量
origin:搜索的起始位置
返回值:無
origin 表示搜索的起始位置,有以下幾個值:
SEEK_CUR 或 1 :當(dāng)前文件指針的位置
SEEK_END 或 2 :文件末尾
SEEK_SET 或 0 :文件開始
fseek和ftell的綜合應(yīng)用,示例:
int main() {FILE *fp;int nLength = 0;fp =fopen(“1.txt”,”r+”);if(fp == NULL){printf(“open failed\n”);return -1;}fseek(fp,0,SEEK_END);//偏移到文件尾部nLength = ftell(fp);//獲取當(dāng)前文件指針離文件開頭的字節(jié)數(shù)printf(“the file length is %d\n”, nLength);fclose(fp); }字符輸入輸出函數(shù)(fputc()和fgetc())
1、fputc()函數(shù)
函數(shù)調(diào)用:int fputc(int ch,FILE *fp) ;
函數(shù)功能:
將字符(ch的值)輸出到fp所指向的文件中去。
返回值:
如果輸出成功,則返回值就是輸出的字符;
如果輸出失敗,則返回一個EOF.
2、fgetc()函數(shù)
函數(shù)調(diào)用:int fgetc(FILE *fp)
函數(shù)功能:
從指定的文件讀入一個字符,該文件必須是以讀或讀寫方式打開的。
返回值:
讀取成功一個字符,賦給ch。如果遇到文件結(jié)束符,返回一個文件結(jié)束標(biāo)志
EOF 。
常見的讀取字符操作:
①從一個文本文件順序讀入字符并在屏幕上顯示出來:
#include<stdio.h> #include <stdlib.h> #include <string.h> int main() {FILE *fp;char ch;char string[ ] = "This is a test";fp = fopen("1.txt","w+");fwrite(string, strlen(string), 1, fp); //將string寫入文件fseek(fp, 0, SEEK_SET); //將文件指針設(shè)到起始位置ch = fgetc(fp);while(ch != EOF){putchar(ch);ch = fgetc(fp);} return 0; }注意:EOF不是可輸出字符,因此不能在屏幕上顯示。由于字符的ASCII碼不可能出現(xiàn)-1,因此EOF定義為-1是合適的。當(dāng)讀入的字符值等于-1時,表示讀入的已不是正常的字符而是文件結(jié)束符。
②從一個二進(jìn)制文件順序讀入字符:
#include<stdio.h> #include <stdlib.h> #include <string.h> int main() {FILE *fp;char ch;char string[ ] = "This is a test";fp = fopen("1.dat","w+");fwrite(string, strlen(string), 1, fp);fseek(fp, 0, SEEK_SET);while(!feof(fp)) //判斷文件不是真的結(jié)束,循環(huán){ch = fgetc(fp);putchar(ch);} return 0; }注意:ANSI C提供一個feof()函數(shù)來判斷文件是否真的結(jié)束。如果是文件結(jié)束,函數(shù)feof(fp)的值為1(真);否則為0(假)。以上也適用于文本文件的讀取。
fwrite()函數(shù)
功能說明:fwrite是無格式寫函數(shù),用于向文件寫入整塊的數(shù)據(jù)。最有價值的一個應(yīng)用就是讀寫用戶定義的數(shù)據(jù)類型,尤其是結(jié)構(gòu)。
函數(shù)原型:size_t fwrite(const void *buffer,size_t bytes, sizeo_t n,FILE *fp);
參數(shù):buffer:要寫入數(shù)據(jù)的首地址
bytes:一個單元占字節(jié)數(shù)
n:寫入幾個單元
fp:操作的文件指針
返回值:成功時返回寫入的單元數(shù),否則返回0
fread()函數(shù)
功能說明:fread是無格式讀函數(shù),用于向文件讀出整塊的數(shù)據(jù)。經(jīng)常用fwrite函數(shù)寫入,讀取時用fread函數(shù)
函數(shù)原型:size_t fread(void *buffer, size_t bytes, sizeo_t n, FILE *fp);
參數(shù):buffer:接收緩沖區(qū)的首地址
bytes:一個單元占字節(jié)數(shù)
n:讀出幾個單元
fp:操作的文件指針
返回值:成功時返回讀出的單元數(shù),否則返回0
fread與fwrite實例:
#include<stdio.h> #include <stdlib.h> #include <string.h>int main() {FILE *fp;char ch;char string[1024] = "This is a test";char rdata[1024];fp = fopen("1.txt","w+");fwrite(string, sizeof(string), 1, fp);fseek(fp, 0, SEEK_SET);fread(rdata,sizeof(rdata),1,fp); //這里fread的sizeof的大小和fwrite的一直,不然會打印結(jié)果后出現(xiàn)亂碼或顯示不全printf("rdata = %s\n",rdata);return 0; }運行結(jié)果: rdata = This is a test格式化讀寫函數(shù)(fprintf()和fscanf())
函數(shù)調(diào)用:
int fscanf(文件指針,格式字符串,輸入表列);
int fprintf(文件指針,格式字符串,輸出表列);
函數(shù)功能:
從磁盤文件中讀入或輸出字符。
例:
fprintf(fp,"%d,%6.2f",i,t); fscanf(fp,"%d,%f",&i,&t);注意:用fprintf和fscanf函數(shù)對磁盤文件讀寫,使用方便,容易理解,但由于在輸入時要將ASCII碼轉(zhuǎn)換為二進(jìn)制形式,在輸出時又要將二進(jìn)制形式轉(zhuǎn)換成字符,花費時間比較多。因此,在內(nèi)存與磁盤頻繁交換數(shù)據(jù)的情況下,最好不用fprintf和fscanf函數(shù),而用fread和fwrite函數(shù)。
putw()和getw()
函數(shù)調(diào)用:
int putw(int w,FILE * fp);
int getw(FILE * fp);
函數(shù)功能: 對磁盤文件中讀寫一個字(以二進(jìn)制形式從文件流中讀取整數(shù))。
注意:putw()和getw()都是按二進(jìn)制輸入輸出的。所以如果你用putw()輸入數(shù)據(jù)到文件后以文本的方式打開看到的將都是亂碼。
同樣如果你在文本文件中輸入了數(shù)字并保存,用getw()來讀入的話讀入的結(jié)果并不是你想象的那樣,因為它是按二進(jìn)制讀的。
實例:
#include<stdio.h> #include <stdlib.h> #include <string.h>int main() {FILE *fp;int w;fp = fopen("2.txt","wb"); //以二進(jìn)制形式寫putw(5,fp); fclose(fp);fp = fopen("2.txt","rb");//以二進(jìn)制形式讀w = getw(fp);printf("Successful read: w = %d\n", w);fclose(fp);return 0; }fgets函數(shù)
函數(shù)作用:從指定文件讀入一個字符串。
函數(shù)調(diào)用:fgets(str,n,fp);
從fp指向的文件輸入n-1個字符,在最后加一個’\0’
返回值:str的首地址
fputs函數(shù)
函數(shù)作用:
向指定的文件輸出一個字符串。
函數(shù)調(diào)用:fgets("china",fp);
第一個參數(shù)可以是字符串常量、字符數(shù)組名或字符型
指針。字符串末尾的′\0′不輸出。
返回值:
輸入成功,返回值為0;
輸入失敗,返回EOF.
ferror函數(shù)(出錯的檢測)
調(diào)用形式:ferror(fp);
返回值:返回0,表示未出錯;返回非0,表示出錯。
在調(diào)用一個輸入輸出函數(shù)后立即檢查ferror函數(shù)的值,否則信息會丟失。在執(zhí)行fopen函數(shù)時,ferror函數(shù)的初始值自動置為0。
clearerr函數(shù)(出錯的檢測)
調(diào)用形式:clearerr(fp);
函數(shù)作用:使文件錯誤標(biāo)志和文件結(jié)束標(biāo)志置為0。
只要出現(xiàn)錯誤標(biāo)志,就一直保留,直到對同一文件調(diào)用clearerr函數(shù)或rewind函數(shù),或任何其他一個輸入輸出函數(shù)。
總結(jié)
- 上一篇: C语言—通用链表
- 下一篇: C语言—静态存储与动态存储