C語(yǔ)言文件操作

語(yǔ)言中對(duì)文件進(jìn)行操作必須首先打開(kāi)文件,打開(kāi)文件主要涉及到fopen函數(shù)。fopen函數(shù)的原型為

FILE* fopen(const char *path,const char *mode)

其中path為文件路徑,mode為打開(kāi)方式

1)對(duì)于文件路徑,只需注意若未明確給出絕對(duì)路徑,則默認(rèn)該文件在工程的目錄下。若需給出絕對(duì)路徑,則注意轉(zhuǎn)義字符'\\',比如有文件test.txt存放在C盤根目錄下,則文件路徑參數(shù)值應(yīng)為C:\\\\test.txt。

2)對(duì)于mode,主要由r,w,a,+,b,t六個(gè)字符組合而成。

r:只讀方式,文件必須存在

w:只寫方式,若文件存在,則原有內(nèi)容會(huì)被清除;若文件不存在,則會(huì)建立文件

a:追加方式打開(kāi)只寫文件,只允許進(jìn)行寫操作,若文件存在,則添加的內(nèi)容放在文件末尾;若不存在,則建立文件

+:可讀可寫

b:以二進(jìn)制方式打開(kāi)文件

t:以文本方式打開(kāi)文件(默認(rèn)方式下以文本方式打開(kāi)文件)

下面是常見(jiàn)的組合:

r: ? ? ?以只讀的方式打開(kāi)文件,只允許讀,此文件必須存在,否則返回NULL,打開(kāi)成功后返回文件指針,位置指針指向文件頭部

r+: ? ?以可讀可寫的方式打開(kāi)文件,允許讀寫,此文件必須存在,否則返回NULL,打開(kāi)成功后返回文件指針,位置指針指向文件頭部

rb+: ?以可讀可寫、二進(jìn)制方式打開(kāi)文件,允許讀寫,此文件必須存在,否則返回NULL,打開(kāi)成功后返回文件指針,位置指針指向文件頭部

rt+: ?以可讀可寫、文本方式打開(kāi)文件,允許讀寫,此文件必須存在,否則返回NULL,打開(kāi)成功后返回文件指針,位置指針指向文件頭部

w: ? ?以只寫的方式打開(kāi)文件,只允許寫,若文件存在,文件中原有內(nèi)容會(huì)被清除;若文件不存在,則創(chuàng)建文件,打開(kāi)成功后返回文件指針,位置指針指向文件頭部

w+: ?以讀寫的方式打開(kāi)文件,允許讀寫,若文件存在,文件中原有內(nèi)容會(huì)被清除;若文件不存在,則創(chuàng)建文件,打開(kāi)成功后返回文件指針,位置指針指向文件頭部

a: ? ? 以追加、只寫的方式打開(kāi)文件,只允許寫。若文件存在,則追加的內(nèi)容添加在文件末尾,若文件不存在,則創(chuàng)建文件。打開(kāi)成功后返回文件指針,位置指針指向文件頭部(注意很多書(shū)上或資料上講述追加方式打開(kāi)成功后位置指針指向文件末尾是錯(cuò)誤的)

a+: ? 以追加、可讀寫的方式打開(kāi)文件,允許讀寫。若進(jìn)行讀操作,則從頭開(kāi)始讀;若進(jìn)行寫操作,則將內(nèi)容添加在末尾。若文件不存在,則創(chuàng)建文件。打開(kāi)成功后返回文件指針,位置指針指向文件頭部。

其他方式類似。

下面討論一下以二進(jìn)制方式和文本方式打開(kāi)文件有什么區(qū)別。

其實(shí)這兩種方式打開(kāi)文件并沒(méi)有太大的區(qū)別,僅僅只有一點(diǎn)區(qū)別就是在處理某些特殊字符的時(shí)候。

以文本方式打開(kāi)文件,若將數(shù)據(jù)寫入文件,如果遇到換行符'\\n'(ASII

值為10,0A),則會(huì)轉(zhuǎn)換為回車—換行'\\r\\n'(ASII值為13,10,0D0A)存入到文件中,同樣讀取的時(shí)候,若遇到回車—換行,即連續(xù)的

ASII值13,10,則自動(dòng)轉(zhuǎn)換為換行符。

而以二進(jìn)制方式打開(kāi)文件時(shí),不會(huì)進(jìn)行這樣的處理。

還有如果以文本方式打開(kāi)文件時(shí),若讀取到ASCII碼為26(^Z)的字符,則停止對(duì)文件的讀取,會(huì)默認(rèn)為文件已結(jié)束,而以二進(jìn)制方式讀取時(shí)不會(huì)發(fā)生這樣

的情況。由于正常情況下我們手動(dòng)編輯完成的文件是不可能出現(xiàn)ASCII碼為26的字符,所以可以用feof函數(shù)去檢測(cè)文件是否結(jié)束。以上所述的兩點(diǎn)區(qū)別只

在windows下存在,在unix下沒(méi)有區(qū)別。

注意:1)在以追加方式打開(kāi)文件時(shí),位置指針指向文件的首部。

在這里區(qū)分一下位置指針和文件指針:

文件指針:指向存儲(chǔ)文件信息的一個(gè)結(jié)構(gòu)體的指針

位置指針:對(duì)文件進(jìn)行讀寫操作時(shí)移動(dòng)的指針

在頭文件中存在一個(gè)結(jié)構(gòu)體_iobuf,在VC6.0中選中FILE,然后F12,則可以看到_iobuf的具體定義:

struct_iobuf {

char*_ptr;

int_cnt;

char*_base;

int_flag;

int_file;

int_charbuf;

int_bufsiz;

char*_tmpfname;

};

typedefstruct_iobuf FILE;

比如用FILE *fp定義了一個(gè)文件指針,并成功打開(kāi)一個(gè)文件之后,fp只是指向該結(jié)構(gòu)體,而在對(duì)文件進(jìn)行讀寫操作時(shí),fp的值并不會(huì)改變,改變的是結(jié)構(gòu)體中_ptr的值,這個(gè)_ptr就是位置指針。

2)以追加方式打開(kāi)時(shí),若進(jìn)行寫操作,則rewind函數(shù)和fseek函數(shù)不會(huì)起到作用,因?yàn)橐宰芳臃绞酱蜷_(kāi)時(shí)進(jìn)行寫操作的話,系統(tǒng)會(huì)自動(dòng)將位置指針移動(dòng)到末尾。

3)當(dāng)文件打開(kāi)用于更新時(shí),可以通過(guò)文件指針對(duì)文件進(jìn)行讀寫操作,但是如果沒(méi)有給出fseek或者rewind的話,讀操作后面不能直接跟寫操作,否則會(huì)是無(wú)效的寫操作(位置指針會(huì)移動(dòng),但是需要寫入文件的內(nèi)容不會(huì)被寫入到文件當(dāng)中),但是寫操作后可以直接跟讀操作。

1.測(cè)試程序

假設(shè)工程目錄下已存在文件test.txt,文件中含有的字符串為"ABC"

/*測(cè)試fopen函數(shù)以追加方式打開(kāi)文件時(shí)初始指針的位置 2011.10.5*/

#include

#include

intmain(void)

{

intn;

FILE *fp;

if((fp=fopen("test.txt","a"))==NULL)

{

printf("can not open file\\n");

exit(0);

}

n=ftell(fp);//得到此時(shí)fp所處位置距文件首的偏移字節(jié)數(shù)

printf("%d\\n",n);

fputs("test",fp);

n=ftell(fp);

printf("%d\\n",n);

fclose(fp);

return0;

}

輸出結(jié)果為:

0

7

Press any key to continue

由輸出結(jié)果可知,初始打開(kāi)文件后,指針是位于文件首部,只是在往文件中添加內(nèi)容時(shí),才將文件指針移動(dòng)到文件末尾。

2.測(cè)試程序

/*測(cè)試以二進(jìn)制方式和文本方式打開(kāi)文件的區(qū)別 2011.10.5*/

#include

#include

intmain(void)

{

charch;

inti;

chars[]={'A','B','\\n','C'};

FILE *fp1,*fp2;

if((fp1=fopen("test1.txt","wt"))==NULL)

{

printf("can not open file\\n");

exit(0);

}

if((fp2=fopen("test2.txt","wb"))==NULL)

{

printf("can not open file\\n");

exit(0);

}

for(i=0;i<4;i++)

{

fputc(s[i],fp1);//以文本方式向文件中寫入數(shù)據(jù)

fputc(s[i],fp2);//以二進(jìn)制方式向文件中寫入數(shù)據(jù)

}

fclose(fp1);

fclose(fp2);

if((fp1=fopen("test1.txt","rt"))==NULL)

{

printf("can not open file\\n");

exit(0);

}

if((fp2=fopen("test1.txt","rb"))==NULL)

{

printf("can not open file\\n");

exit(0);

}

ch=fgetc(fp1);

while(!feof(fp1))//以文本方式從文件中讀取數(shù)據(jù)

{

printf("%02X",ch);

ch=fgetc(fp1);

}

printf("\\n");

ch=fgetc(fp2);

while(!feof(fp2))//以二進(jìn)制方式從文件中讀取數(shù)據(jù)

{

printf("%02X",ch);

ch=fgetc(fp2);

}

printf("\\n");

fclose(fp1);

fclose(fp2);

return0;

}

在向文件中寫完數(shù)據(jù)后,用UltraEdit以二進(jìn)制方式打開(kāi)test1.txt和test2.txt,看到的結(jié)果如下:

根據(jù)得到的結(jié)果可知,以文本方式寫入時(shí),多寫入了一個(gè)字符0D,即'\\r'。

程序輸出結(jié)果:

41420A43

41420D0A43

請(qǐng)按任意鍵繼續(xù). . .

分別以文本方式和二進(jìn)制方式讀取test1.txt時(shí),輸出的內(nèi)容不同。

可知在以文本方式讀取時(shí),對(duì)'\\r\\n'進(jìn)行了轉(zhuǎn)換,而二進(jìn)制方式讀取時(shí)卻沒(méi)有進(jìn)行這樣的轉(zhuǎn)換(要注意,windows和linux下的換行符是不一樣的,在windows下?lián)Q行符是\\r\\n,即0X0D、0X0A,而在linux下?lián)Q行符是\\n,即0X0A。

3.測(cè)試程序

/*測(cè)試讀操作后能否直接跟寫操作 2011.10.5*/

#include

#include

intmain(void)

{

intch;

intn;

FILE *fp;

if((fp=fopen("test.txt","r+"))==NULL)

{

printf("can not open file\\n");

exit(0);

}

fseek(fp,1L,0);//將fp移動(dòng)到距文件首1字節(jié)的位置

ch=fgetc(fp);

printf("%c\\n",ch);

//rewind(fp);

fseek(fp,1L,0);

fputs("test",fp);

ch=fgetc(fp);

printf("%c\\n",ch);

fclose(fp);

return0;

}

假設(shè)工程已經(jīng)存在文件test.txt,文件中含有字符串"ABCDEFGH"。

則上述程序執(zhí)行結(jié)果為:

B

F

請(qǐng)按任意鍵繼續(xù). . .文件中內(nèi)容為"AtestFGH"。

與預(yù)想結(jié)果相同,因此讀取到字符'B'后,再將位置指針置到距文件首1字節(jié)處,即字符'B'處,寫入"test"后,會(huì)覆蓋掉"BCDE",寫完后位置指針指向字符'F',因此此時(shí)進(jìn)行讀操作,得到的結(jié)果是'F'。

但是如果將fseek(fp,1L,0);這句注釋掉,則執(zhí)行結(jié)果為:

B

G

請(qǐng)按任意鍵繼續(xù). . .

文件中的內(nèi)容為"ABCDEFGH"。

注釋掉fseek一句后,讀取完字符'B'后,位置指針指向字符'C',再進(jìn)行寫操作,位置指針會(huì)向后移動(dòng)4個(gè)字節(jié)的位置,指向字符'G',因此第二次讀取的輸出結(jié)果為'G'。但是文件中的內(nèi)容沒(méi)有被改寫,相當(dāng)于這次寫操作是無(wú)效操作。

4.測(cè)試程序

#include

#include

intmain(void)

{

FILE *fp;

intch;

if((fp=fopen("test","rb"))==NULL)

{

printf("can not open file\\n");

exit(0);

}

ch=fgetc(fp);

while(feof(fp)==0)

{

printf("%02X\\n",ch);

ch=fgetc(fp);

}

fclose(fp);

return0;

}

運(yùn)行此程序之前,用VC6.0建立一個(gè)二進(jìn)制文件test放在工程目錄下,然后輸入數(shù)據(jù)"23 13 0E 1A 35"。保存完畢后再執(zhí)行此程序,執(zhí)行結(jié)果為:

23

13

0E

1A

35

Press any key to continue

但是若將打開(kāi)方式改成"rt",則執(zhí)行結(jié)果為:

23

13

0E

Press any key to continue

之所以出現(xiàn)這種原因,在上面已經(jīng)提到,就是在以文本方式打開(kāi)文件時(shí),若讀取到ASCII碼為26的字符,則會(huì)停止讀取,默認(rèn)文件內(nèi)容已經(jīng)結(jié)束。但是以二進(jìn)制方式打開(kāi)文件則不會(huì)出現(xiàn)這種情況,會(huì)將文件中所有的內(nèi)容原樣輸出(注意這種區(qū)別只在windows下存在,在unix下兩種方式打開(kāi)文件程序的執(zhí)行結(jié)果是相同的即會(huì)原樣輸出文件中所有的內(nèi)容)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 第1章 第一個(gè)C程序第2章 C語(yǔ)言基礎(chǔ)第3章 變量和數(shù)據(jù)類型第4章 順序結(jié)構(gòu)程序設(shè)計(jì)第5章 條件結(jié)構(gòu)程序設(shè)計(jì)第6章...
    小獅子365閱讀 10,857評(píng)論 3 71
  • 文件指針 FILE * 指針變量標(biāo)識(shí)符作用:通過(guò)該指針即可找到存放某個(gè)文件信息的結(jié)構(gòu)變量,然后按結(jié)構(gòu)變量提供的信息...
    永斷閻羅閱讀 499評(píng)論 0 3
  • 不知道是不是在城里生活久了,天天上班下班,跟周圍的人交流也少,一顆心也開(kāi)始有了盔甲,不在那么的平易近人了。 ...
    歡喜十一閱讀 267評(píng)論 1 0
  • 今天犯了一個(gè)錯(cuò)誤,將“一字千金“詮釋的如此淋淋盡致。 昨天約了小貨車去深圳鹽田區(qū)保稅倉(cāng)送貨入庫(kù),因上次去鹽田保稅倉(cāng)...
    llnntt閱讀 224評(píng)論 0 0
  • 剛接觸Markdown,總結(jié)一些常用語(yǔ)法,希望能幫助一些像我一樣的初學(xué)者快速入門。 一、段落前面的空格 輸入法切換...
    sunnygarden閱讀 1,068評(píng)論 0 1

友情鏈接更多精彩內(nèi)容