c語(yǔ)言文件讀寫(xiě)怎么操作-當(dāng)前動(dòng)態(tài)

          來(lái)源:php中文網(wǎng) | 2023-01-05 14:56:57 |

          本教程操作環(huán)境:windows7系統(tǒng)、c99版本、Dell G3電腦。

          在C語(yǔ)言中,讀寫(xiě)文件比較靈活,既可以每次讀寫(xiě)一個(gè)字符,也可以讀寫(xiě)一個(gè)字符串,甚至是任意字節(jié)的數(shù)據(jù)(數(shù)據(jù)塊)。


          (相關(guān)資料圖)

          以字符形式讀寫(xiě)文件

          以字符形式讀寫(xiě)文件時(shí),每次可以從文件中讀取一個(gè)字符,或者向文件中寫(xiě)入一個(gè)字符。主要使用兩個(gè)函數(shù),分別是 fgetc() 和 fputc()。

          1、字符讀取函數(shù) fgetc

          fgetc 是 file get char 的縮寫(xiě),意思是從指定的文件中讀取一個(gè)字符。fgetc() 的用法為:

          int fgetc (FILE *fp);

          fp 為文件指針。fgetc() 讀取成功時(shí)返回讀取到的字符,讀取到文件末尾或讀取失敗時(shí)返回EOF。

          EOF 是 end of file 的縮寫(xiě),表示文件末尾,是在 stdio.h 中定義的宏,它的值是一個(gè)負(fù)數(shù),往往是 -1。fgetc() 的返回值類型之所以為 int,就是為了容納這個(gè)負(fù)數(shù)(char不能是負(fù)數(shù))。

          EOF 不絕對(duì)是 -1,也可以是其他負(fù)數(shù),這要看編譯器的實(shí)現(xiàn)。

          fgetc() 的用法舉例:

          char ch;FILE *fp = fopen("D:\\demo.txt", "r+");ch = fgetc(fp);

          表示從D:\\demo.txt文件中讀取一個(gè)字符,并保存到變量 ch 中。

          在文件內(nèi)部有一個(gè)位置指針,用來(lái)指向當(dāng)前讀寫(xiě)到的位置,也就是讀寫(xiě)到第幾個(gè)字節(jié)。在文件打開(kāi)時(shí),該指針總是指向文件的第一個(gè)字節(jié)。使用 fgetc() 函數(shù)后,該指針會(huì)向后移動(dòng)一個(gè)字節(jié),所以可以連續(xù)多次使用 fgetc() 讀取多個(gè)字符。

          注意:這個(gè)文件內(nèi)部的位置指針與C語(yǔ)言中的指針不是一回事。位置指針僅僅是一個(gè)標(biāo)志,表示文件讀寫(xiě)到的位置,也就是讀寫(xiě)到第幾個(gè)字節(jié),它不表示地址。文件每讀寫(xiě)一次,位置指針就會(huì)移動(dòng)一次,它不需要你在程序中定義和賦值,而是由系統(tǒng)自動(dòng)設(shè)置,對(duì)用戶是隱藏的。

          【示例】在屏幕上顯示 D:\\demo.txt 文件的內(nèi)容。

          #include<stdio.h>int main(){    FILE *fp;    char ch;       //如果文件不存在,給出提示并退出    if( (fp=fopen("D:\\demo.txt","rt")) == NULL ){        puts("Fail to open file!");        exit(0);    }    //每次讀取一個(gè)字節(jié),直到讀取完畢    while( (ch=fgetc(fp)) != EOF ){        putchar(ch);    }    putchar("\n");  //輸出換行符    fclose(fp);    return 0;}

          在D盤下創(chuàng)建 demo.txt 文件,輸入任意內(nèi)容并保存,運(yùn)行程序,就會(huì)看到剛才輸入的內(nèi)容全部都顯示在屏幕上。

          該程序的功能是從文件中逐個(gè)讀取字符,在屏幕上顯示,直到讀取完畢。

          程序第 13 行是關(guān)鍵,while 循環(huán)的條件為(ch=fgetc(fp)) != EOF。fget() 每次從位置指針?biāo)诘奈恢米x取一個(gè)字符,并保存到變量 ch,位置指針向后移動(dòng)一個(gè)字節(jié)。當(dāng)文件指針移動(dòng)到文件末尾時(shí),fget() 就無(wú)法讀取字符了,于是返回 EOF,表示文件讀取結(jié)束了。

          對(duì) EOF 的說(shuō)明:

          EOF 本來(lái)表示文件末尾,意味著讀取結(jié)束,但是很多函數(shù)在讀取出錯(cuò)時(shí)也返回 EOF,那么當(dāng)返回 EOF 時(shí),到底是文件讀取完畢了還是讀取出錯(cuò)了?我們可以借助 stdio.h 中的兩個(gè)函數(shù)來(lái)判斷,分別是 feof() 和 ferror()。

          feof() 函數(shù)用來(lái)判斷文件內(nèi)部指針是否指向了文件末尾,它的原型是:

          int feof ( FILE * fp );

          當(dāng)指向文件末尾時(shí)返回非零值,否則返回零值。

          ferror() 函數(shù)用來(lái)判斷文件操作是否出錯(cuò),它的原型是:

          int ferror ( FILE *fp );

          出錯(cuò)時(shí)返回非零值,否則返回零值。

          需要說(shuō)明的是,文件出錯(cuò)是非常少見(jiàn)的情況,上面的示例基本能夠保證將文件內(nèi)的數(shù)據(jù)讀取完畢。如果追求完美,也可以加上判斷并給出提示:

          #include<stdio.h>int main(){    FILE *fp;    char ch;      //如果文件不存在,給出提示并退出    if( (fp=fopen("D:\\demo.txt","rt")) == NULL ){        puts("Fail to open file!");        exit(0);    }    //每次讀取一個(gè)字節(jié),直到讀取完畢    while( (ch=fgetc(fp)) != EOF ){        putchar(ch);    }    putchar("\n");  //輸出換行符    if(ferror(fp)){        puts("讀取出錯(cuò)");    }else{        puts("讀取成功");    }    fclose(fp);    return 0;}

          這樣,不管是出錯(cuò)還是正常讀取,都能夠做到心中有數(shù)。

          2、字符寫(xiě)入函數(shù) fputc

          fputc 是 file output char 的所以,意思是向指定的文件中寫(xiě)入一個(gè)字符。fputc() 的用法為:

          int fputc ( int ch, FILE *fp );

          ch 為要寫(xiě)入的字符,fp 為文件指針。fputc() 寫(xiě)入成功時(shí)返回寫(xiě)入的字符,失敗時(shí)返回 EOF,返回值類型為 int 也是為了容納這個(gè)負(fù)數(shù)。例如:

          fputc("a", fp);

          或者:

          char ch = "a";fputc(ch, fp);

          表示把字符 "a" 寫(xiě)入fp所指向的文件中。

          兩點(diǎn)說(shuō)明

          1) 被寫(xiě)入的文件可以用寫(xiě)、讀寫(xiě)、追加方式打開(kāi),用寫(xiě)或讀寫(xiě)方式打開(kāi)一個(gè)已存在的文件時(shí)將清除原有的文件內(nèi)容,并將寫(xiě)入的字符放在文件開(kāi)頭。如需保留原有文件內(nèi)容,并把寫(xiě)入的字符放在文件末尾,就必須以追加方式打開(kāi)文件。不管以何種方式打開(kāi),被寫(xiě)入的文件若不存在時(shí)則創(chuàng)建該文件。

          2) 每寫(xiě)入一個(gè)字符,文件內(nèi)部位置指針向后移動(dòng)一個(gè)字節(jié)。

          【示例】從鍵盤輸入一行字符,寫(xiě)入文件。

          #include<stdio.h>int main(){    FILE *fp;    char ch;    //判斷文件是否成功打開(kāi)    if( (fp=fopen("D:\\demo.txt","wt+")) == NULL ){        puts("Fail to open file!");        exit(0);    }    printf("Input a string:\n");    //每次從鍵盤讀取一個(gè)字符并寫(xiě)入文件    while ( (ch=getchar()) != "\n" ){        fputc(ch,fp);    }    fclose(fp);    return 0;}

          運(yùn)行程序,輸入一行字符并按回車鍵結(jié)束,打開(kāi)D盤下的 demo.txt 文件,就可以看到剛才輸入的內(nèi)容。

          程序每次從鍵盤讀取一個(gè)字符并寫(xiě)入文件,直到按下回車鍵,while 條件不成立,結(jié)束讀取。

          以字符串的形式讀寫(xiě)文件

          fgetc() 和 fputc() 函數(shù)每次只能讀寫(xiě)一個(gè)字符,速度較慢;實(shí)際開(kāi)發(fā)中往往是每次讀寫(xiě)一個(gè)字符串或者一個(gè)數(shù)據(jù)塊,這樣能明顯提高效率。

          1、讀字符串函數(shù) fgets

          fgets() 函數(shù)用來(lái)從指定的文件中讀取一個(gè)字符串,并保存到字符數(shù)組中,它的用法為:

          char *fgets ( char *str, int n, FILE *fp );

          str 為字符數(shù)組,n 為要讀取的字符數(shù)目,fp 為文件指針。

          返回值:讀取成功時(shí)返回字符數(shù)組首地址,也即 str;讀取失敗時(shí)返回 NULL;如果開(kāi)始讀取時(shí)文件內(nèi)部指針已經(jīng)指向了文件末尾,那么將讀取不到任何字符,也返回 NULL。

          注意,讀取到的字符串會(huì)在末尾自動(dòng)添加 "\0",n 個(gè)字符也包括 "\0"。也就是說(shuō),實(shí)際只讀取到了 n-1 個(gè)字符,如果希望讀取 100 個(gè)字符,n 的值應(yīng)該為 101。例如:

          #define N 101char str[N];FILE *fp = fopen("D:\\demo.txt", "r");fgets(str, N, fp);

          表示從 D:\\demo.txt 中讀取 100 個(gè)字符,并保存到字符數(shù)組 str 中。

          需要重點(diǎn)說(shuō)明的是,在讀取到 n-1 個(gè)字符之前如果出現(xiàn)了換行,或者讀到了文件末尾,則讀取結(jié)束。這就意味著,不管 n 的值多大,fgets() 最多只能讀取一行數(shù)據(jù),不能跨行。在C語(yǔ)言中,沒(méi)有按行讀取文件的函數(shù),我們可以借助 fgets(),將 n 的值設(shè)置地足夠大,每次就可以讀取到一行數(shù)據(jù)。

          【示例】一行一行地讀取文件。

          #include <stdio.h>#include <stdlib.h>#define N 100int main(){    FILE *fp;    char str[N+1];    if( (fp=fopen("d:\\demo.txt","rt")) == NULL ){        puts("Fail to open file!");        exit(0);    }       while(fgets(str, N, fp) != NULL){        printf("%s", str);    }    fclose(fp);    return 0;}

          將下面的內(nèi)容復(fù)制到 D:\\demo.txt:

          PHP中文網(wǎng)https://www.php.cn/

          那么運(yùn)行結(jié)果為:

          fgets() 遇到換行時(shí),會(huì)將換行符一并讀取到當(dāng)前字符串。該示例的輸出結(jié)果之所以和 demo.txt 保持一致,該換行的地方換行,就是因?yàn)?fgets() 能夠讀取到換行符。而 gets() 不一樣,它會(huì)忽略換行符。

          2、寫(xiě)字符串函數(shù) fputs

          fputs() 函數(shù)用來(lái)向指定的文件寫(xiě)入一個(gè)字符串,它的用法為:

          int fputs( char *str, FILE *fp );

          str 為要寫(xiě)入的字符串,fp 為文件指針。寫(xiě)入成功返回非負(fù)數(shù),失敗返回 EOF。例如:

          char *str = "http://c.biancheng.net";FILE *fp = fopen("D:\\demo.txt", "at+");fputs(str, fp);

          表示把把字符串 str 寫(xiě)入到 D:\\demo.txt 文件中。

          【示例】向上例中建立的 d:\\demo.txt 文件中追加一個(gè)字符串。

          #include<stdio.h>int main(){    FILE *fp;    char str[102] = {0}, strTemp[100];    if( (fp=fopen("D:\\demo.txt", "at+")) == NULL ){        puts("Fail to open file!");        exit(0);    }    printf("Input a string:");    gets(strTemp);    strcat(str, "\n");    strcat(str, strTemp);    fputs(str, fp);    fclose(fp);    return 0;}

          運(yùn)行程序,輸入C C++ Java Linux Shell,打開(kāi) D:\\demo.txt,文件內(nèi)容為:

          以數(shù)據(jù)塊的形式讀寫(xiě)文件

          fgets() 有局限性,每次最多只能從文件中讀取一行內(nèi)容,因?yàn)?fgets() 遇到換行符就結(jié)束讀取。如果希望讀取多行內(nèi)容,需要使用 fread() 函數(shù);相應(yīng)地寫(xiě)入函數(shù)為 fwrite()。

          對(duì)于 Windows 系統(tǒng),使用 fread() 和 fwrite() 時(shí)應(yīng)該以二進(jìn)制的形式打開(kāi)文件。

          fread() 函數(shù)用來(lái)從指定文件中讀取塊數(shù)據(jù)。所謂塊數(shù)據(jù),也就是若干個(gè)字節(jié)的數(shù)據(jù),可以是一個(gè)字符,可以是一個(gè)字符串,可以是多行數(shù)據(jù),并沒(méi)有什么限制。fread() 的原型為:

          size_t fread ( void *ptr, size_t size, size_t count, FILE *fp );

          fwrite() 函數(shù)用來(lái)向文件中寫(xiě)入塊數(shù)據(jù),fwrite() 函數(shù)的原型為:

          size_t fwrite ( void * ptr, size_t size, size_t count, FILE *fp );

          對(duì)參數(shù)的說(shuō)明:

          ptr 為內(nèi)存區(qū)塊的指針,它可以是數(shù)組、變量、結(jié)構(gòu)體等。fread() 中的 ptr 用來(lái)存放讀取到的數(shù)據(jù),fwrite() 中的 ptr 用來(lái)存放要寫(xiě)入的數(shù)據(jù)。

          size:表示每個(gè)數(shù)據(jù)塊的字節(jié)數(shù)。

          count:表示要讀寫(xiě)的數(shù)據(jù)塊的塊數(shù)。

          fp:表示文件指針。

          理論上,每次讀寫(xiě) size*count 個(gè)字節(jié)的數(shù)據(jù)。

          size_t 是在 stdio.h 和 stdlib.h 頭文件中使用 typedef 定義的數(shù)據(jù)類型,表示無(wú)符號(hào)整數(shù),也即非負(fù)數(shù),常用來(lái)表示數(shù)量。

          返回值:返回成功讀寫(xiě)的塊數(shù),也即 count。如果返回值小于 count:

          對(duì)于 fwrite() 來(lái)說(shuō),肯定發(fā)生了寫(xiě)入錯(cuò)誤,可以用 ferror() 函數(shù)檢測(cè)。

          對(duì)于 fread() 來(lái)說(shuō),可能讀到了文件末尾,可能發(fā)生了錯(cuò)誤,可以用 ferror() 或 feof() 檢測(cè)。

          【示例】從鍵盤輸入一個(gè)數(shù)組,將數(shù)組寫(xiě)入文件再讀取出來(lái)。

          #include<stdio.h>#define N 5int main(){    //從鍵盤輸入的數(shù)據(jù)放入a,從文件讀取的數(shù)據(jù)放入b    int a[N], b[N];    int i, size = sizeof(int);    FILE *fp;    if( (fp=fopen("D:\\demo.txt", "rb+")) == NULL ){  //以二進(jìn)制方式打開(kāi)        puts("Fail to open file!");        exit(0);    }      //從鍵盤輸入數(shù)據(jù) 并保存到數(shù)組a    for(i=0; i<N; i++){        scanf("%d", &a[i]);    }    //將數(shù)組a的內(nèi)容寫(xiě)入到文件    fwrite(a, size, N, fp);    //將文件中的位置指針重新定位到文件開(kāi)頭    rewind(fp);    //從文件讀取內(nèi)容并保存到數(shù)組b    fread(b, size, N, fp);    //在屏幕上顯示數(shù)組b的內(nèi)容    for(i=0; i<N; i++){        printf("%d ", b[i]);    }    printf("\n");    fclose(fp);    return 0;}

          運(yùn)行結(jié)果:

          23 409 500 100 222↙23 409 500 100 222

          打開(kāi) D:\\demo.txt,發(fā)現(xiàn)文件內(nèi)容根本無(wú)法閱讀。這是因?yàn)槲覀兪褂?rb+"方式打開(kāi)文件,數(shù)組會(huì)原封不動(dòng)地以二進(jìn)制形式寫(xiě)入文件,一般無(wú)法閱讀。

          數(shù)據(jù)寫(xiě)入完畢后,位置指針在文件的末尾,要想讀取數(shù)據(jù),必須將文件指針移動(dòng)到文件開(kāi)頭,這就是rewind(fp);的作用。更多關(guān)于rewind函數(shù)的內(nèi)容請(qǐng)點(diǎn)擊:C語(yǔ)言rewind函數(shù)。

          文件的后綴不一定是 .txt,它可以是任意的,你可以自己命名,例如 demo.ddd、demo.doc、demo.diy 等。

          【示例】從鍵盤輸入兩個(gè)學(xué)生數(shù)據(jù),寫(xiě)入一個(gè)文件中,再讀出這兩個(gè)學(xué)生的數(shù)據(jù)顯示在屏幕上。

          #include<stdio.h>#define N 2struct stu{    char name[10]; //姓名    int num;  //學(xué)號(hào)    int age;  //年齡    float score;  //成績(jī)}boya[N], boyb[N], *pa, *pb;int main(){    FILE *fp;    int i;    pa = boya;    pb = boyb;    if( (fp=fopen("d:\\demo.txt", "wb+")) == NULL ){        puts("Fail to open file!");        exit(0);    }    //從鍵盤輸入數(shù)據(jù)    printf("Input data:\n");    for(i=0; i<N; i++,pa++){        scanf("%s %d %d %f",pa->name, &pa->num,&pa->age, &pa->score);    }    //將數(shù)組 boya 的數(shù)據(jù)寫(xiě)入文件    fwrite(boya, sizeof(struct stu), N, fp);    //將文件指針重置到文件開(kāi)頭    rewind(fp);    //從文件讀取數(shù)據(jù)并保存到數(shù)據(jù) boyb    fread(boyb, sizeof(struct stu), N, fp);    //輸出數(shù)組 boyb 中的數(shù)據(jù)    for(i=0; i<N; i++,pb++){        printf("%s  %d  %d  %f\n", pb->name, pb->num, pb->age, pb->score);    }    fclose(fp);    return 0;}

          運(yùn)行結(jié)果:

          Input data:Tom 2 15 90.5↙Hua 1 14 99↙Tom  2  15  90.500000Hua  1  14  99.000000

          以上就是c語(yǔ)言文件讀寫(xiě)怎么操作的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!

          關(guān)鍵詞:

          亚洲人成在线播放网站| 丝袜熟女国偷自产中文字幕亚洲| 五月天婷亚洲天综合网精品偷| 亚洲精品中文字幕无码AV| 亚洲av午夜福利精品一区| 中文字幕在亚洲第一在线| 亚洲乱码国产一区网址| 亚洲av高清在线观看一区二区| 久久亚洲精品无码av| 亚洲精华国产精华精华液| 亚洲国产欧洲综合997久久| 亚洲综合精品成人| 亚洲欧美日韩中文字幕在线一区| 亚洲精品免费网站| 亚洲国产精品自在自线观看| 亚洲AV无码AV男人的天堂不卡 | 国产成人精品日本亚洲直接| 亚洲国产美女福利直播秀一区二区 | 亚洲国产精品综合一区在线| 亚洲日韩乱码中文无码蜜桃| 亚洲日韩在线视频| 亚洲va在线va天堂va手机| 精品亚洲国产成人| 欧洲 亚洲 国产图片综合| 亚洲精品GV天堂无码男同| 一区二区三区亚洲视频| 亚洲精品99久久久久中文字幕| 久久综合亚洲色HEZYO国产| 国产亚洲日韩一区二区三区| 久久精品国产精品亚洲精品| 亚洲男人第一av网站| 亚洲成人网在线观看| 亚洲人成图片网站| 亚洲午夜无码久久| 亚洲乱码在线视频| 亚洲a∨无码男人的天堂| 亚洲国产超清无码专区| 亚洲AV一二三区成人影片| 亚洲AV无码乱码麻豆精品国产| 亚洲熟妇av一区二区三区| 亚洲中文字幕无码日韩|