C語言中的文件操作

C語言中的文件操作

  • 在C語言中霎肯,文件是存儲一連串bytes的數(shù)據(jù)翔试,可以被當(dāng)作文本或者位串來處理
  • 文件也是一種輸入輸出流,被定義在stdio.h中的FILE類型變量
  • FILE *myFile指針指向文件的起始位置
  • EOF是定義在頭文件stdio.h中的常量基矮,值取決于具體實現(xiàn)(通常為-1)聚磺,在操作系統(tǒng)中:Ctrl-Z(Windows熱鍵) Control-D(macOS熱鍵)


1. 打開文件

FILE * fopen(const char * path, const char * mode);
  • path:標(biāo)示文件名string字面量

  • mode:表示訪問模式的string字面量

  • 讀取模式(const char * mode)

    | mode | 介紹 |
    | --- | --- |
    | “r” | 讀取 |
    | “w” | 寫入(如果文件不存在則創(chuàng)建新的文件,如果文件已經(jīng)存在就把文件清空)|
    | “a” | 添加(如果文件不存在則創(chuàng)建新的文件) |
    | “r+” | 打開一個已經(jīng)存在的文件進行讀寫 |
    | “w+” | 打開文件進行讀寫(如果文件已經(jīng)存在把文件清空聂沙,不存在創(chuàng)建新的) |
    | “a+” | 打開文件進行讀寫(如果文件已經(jīng)存在秆麸,從已有文件開頭開始讀,從已有文件結(jié)尾開始寫入及汉;若不存在則創(chuàng)建新的文件) |
    (二進制讀取模式:"rb", "wb", "ab", "rb+", "wb+", "ab+“

  • 注意在C語言中沮趣,文件改變沒有任何確認

  • 如果失敗返回NULL,可能讀取失敗或者到了EOF(使用文件狀態(tài)函數(shù)來判斷)


2. 讀寫文件

2.1 讀寫單個字符:getc / putc

getc:

int getc(FILE *infp);
  • 與用于stdingetchar函數(shù)相似
  • 獲得文件指針指向文件位置的下一個字符
  • 如果下一個字符不存在返回EOF

putc:

int putc(int c, FILE *outfp);
  • 與用于stdoutputchar函數(shù)相似
  • c寫入文件指針指向文件位置的下一個字符
  • 成功返回c的int值坷随,失敗返回EOF


2.2 讀寫字符串:fgets / fputs

fgets:

char * fgets(char *s, int max, FILE *fp)
  • 從fp指向的輸入流中讀取房铭,直到文件中出現(xiàn)\n驻龟,\n也會讀入到文件中(并自動在\n后添加\0
  • s必須保證有足夠的大小去容納輸入的字符串(包括自動添加在結(jié)尾的\0
  • 如果讀取的長度大于max-1,最多有max-1個字符會被讀取缸匪,第max個字符為\0
  • 如果讀取失敗或者讀到EOF返回NULL
  • stdout會在調(diào)用該函數(shù)后自動刷新



fputs:

int fputs(char *s, FILE *fp)
  • 將s指向的字符串寫入到fp指向的流中
  • s必須以’\0’結(jié)尾
  • 如果成功返回0翁狐,失敗返回EOF


2.3 格式化讀寫:fscanf / fprintf

fscanf:

int fscanf(FILE * stream, const char * format, [argument...]);
  • stream:輸入流,可傳入指向讀取文件的指針凌蔬,如果在此傳入stdin露懒,那么等價scanf(C語言將文件和輸入輸出設(shè)備等價)
  • 根據(jù)指定的格式(format)向輸出流(stream)寫入數(shù)據(jù)(argument)
  • 成功就返回讀取到的字符個數(shù),失敗返回EOF



fprintf:

int fprintf(FILE *stream, const char *format, [ argument ]...)
  • 根據(jù)指定的格式向輸出流寫入數(shù)據(jù)
  • stream:輸出流砂心,指向讀取文件的指針隐锭,如果在此傳入stdout,那么等價printf(C語言將文件和輸入輸出設(shè)備等價)
  • 成功就返回寫入到文件的字符個數(shù)计贰,失敗返回一個負數(shù)


2.4 按字節(jié)讀寫:fread / fwrite / fseek

fread:

size_t fread(void *buffer, size_t size, size_t count, FILE *stream) ;
  • 從文件流中讀數(shù)據(jù)钦睡,最多讀取count個項,每個項size個字節(jié)
  • 如果調(diào)用成功返回實際讀取到的項個數(shù)(小于或等于count)躁倒,如果不成功或讀到EOF返回0



fwrite:

size_t fwrite(const void *buffer, size_t size, size_t count, FILE *stream);
  • 向指定的流中寫入count個數(shù)據(jù)荞怒,每個項size個字節(jié)
  • 成功執(zhí)行則返回實際寫入的數(shù)據(jù)個數(shù)



fseek:

int fseek(FILE *stream, long offset, int fromwhere);
  • 設(shè)置文件指針stream的位置
  • stream將指向以fromwhere為基準,偏移offset(指針偏移量)個字節(jié)的位置
  • fromwhere取值:0 / SEEK_SET:文件開頭 1 / SEEK_CUR:當(dāng)前位置 2 / SEEK_END:文件結(jié)尾
  • 執(zhí)行成功返回0秧秉,如果執(zhí)行失敗(比如offset取值大于等于2*1024*1024*1024褐桌,即long的正數(shù)范圍),則不改變stream指向的位置象迎,函數(shù)返回一個非0值



示例:

#include <stdio.h>
#include <string.h>

int main () 
{
   FILE *fp;
   char c[] = "this is tutorialspoint";
   char buffer[100];

   /* w+模式打開文件 */
   fp = fopen("file.txt", "w+");

   /* 將字符串寫入文件 */
   fwrite(c, strlen(c) + 1, 1, fp);

   /* 設(shè)置指針至文件開頭 */
   fseek(fp, 0, SEEK_SET);

   /* 讀取并顯示數(shù)據(jù) */
   fread(buffer, strlen(c) + 1, 1, fp);
   printf("%s\n", buffer);
   
   fclose(fp);
   return(0);
}

輸出:

this is tutorialspoint


3. 關(guān)閉文件

int fclose( FILE *myFile );
  • 將緩存中還未處理的數(shù)據(jù)全部排出至文件
  • 關(guān)閉文件荧嵌,釋放該文件使用的內(nèi)存
  • 成功返回0,失敗返回EOF


4. 其他文件方法

int getw(FILE *fp)
  • 從fp所指向流讀取下一個整型值


int putw(int w, FILE *fp);
  • 往fp指向的流中寫入一個整型值


long ftell(FILE *stream)
  • 得到文件位置指針當(dāng)前位置相對于文件首的偏移字節(jié)數(shù)


void rewind(FILE *stream)
  • 將文件內(nèi)部的位置指針重新指向一個流(數(shù)據(jù)流/文件)的開頭


5. 判斷文件狀態(tài)

注意??:可在fgets等函數(shù)返回NULL時用文件狀態(tài)函數(shù)判斷時讀取發(fā)生了錯誤還是遇到了EOF


int ferror(FILE *fp)
  • 檢查錯誤砾淌,如果在讀取時發(fā)生錯誤返回一個非0值啦撮,反之返回0


int feof(FILE *fp)
  • 檢查是否已經(jīng)到達文件末尾,如果文件結(jié)束返回一個非0值汪厨,反之返回0


6. 緩存(Buffer)

  • 因為處理器和輸入輸出設(shè)備的速度上有很大的差距赃春,所以在中間添加了緩存減少同步時間上的延遲
  • 當(dāng)輸入輸出時,數(shù)據(jù)首先存儲在緩存里(并不會調(diào)用函數(shù)后馬上輸入輸出到流上
  • 緩存填滿的時候才會輸入/輸出到設(shè)備(或者讀取到’/n’
image

強制刷新緩存:fflush

//顯示器
fflush(stdout);
//文件
fflush(outfile);


7. 計算文件大小

#include<stdio.h>

void main(){
    FILE *fp;
    char ch;
    int size = 0;
 
    fp = fopen("MyFile.txt", "r");
    if (fp == NULL){
        printf("文件打開失敗");
    }
    
    /* 將指針移至文件末尾 */
    fseek(fp, 0, 2);  
    /* 獲取末尾位置的偏移量 */  
    size = ftell(fp);   
    printf("文件大小為: %d\n", size);    
    fclose(fp);
}


8. 拷貝文件內(nèi)容

#include<stdio.h>

void main(){   
    FILE *fp1, *fp2;
    char ch;
    int pos;
 
    if ((fp1 = fopen("File_1.txt","r")) == NULL){    
        printf("文件打開失敗");
        return;
    }
    fp2 = fopen("File_2.txt", "w"); 
    
    //將指向文件fp1的指針指向fp1末尾
    fseek(fp1, 0L, SEEK_END); 
    //計算文件fp1的長度
    pos = ftell(fp1);
    //將指向文件fp1的指針指會fp1開頭
    fseek(fp1, 0L, SEEK_SET);
    while (pos--){
        //逐個字符拷貝
        ch = fgetc(fp1);
        fputc(ch, fp2);
    }    
    fcloseall();    
}


9. 逆轉(zhuǎn)文件內(nèi)容

#include<stdio.h>
#include<errno.h>
 
//計算原文件長度
long count_characters(FILE *);
 
void main(){
    int I;
    long cnt;
    char ch, ch1;
    FILE *fp1, *fp2;
 
    if (fp1 = fopen("File_1.txt", "r")) {
        fp2 = fopen("File_2.txt", "w");
        cnt = count_characters(fp1); 
        
        /* 
        將fp1指針指向文件的最后一位字符
        */
        fseek(fp1, -1L, SEEK_END);     
        printf("拷貝字符長度: %d\n", ftell(fp1));
 
        while (cnt){
            ch = fgetc(fp1);
            fputc(ch, fp2);
            //為什么這里移動的是兩個劫乱?
            fseek(fp1, -2L, SEEK_CUR);
            cnt--;
        }
        printf("反轉(zhuǎn)拷貝成功");
    }else{
        perror("Error occured\n");
    }
    fclose(fp1);
    fclose(fp2);
}

/* 
計算文件的長度
*/
long count_characters(FILE *f) {
    fseek(f, -1L, 2);
    long last_pos = ftell(f);
    last_pos++;
    return last_pos;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末织中,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子衷戈,更是在濱河造成了極大的恐慌狭吼,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,378評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件殖妇,死亡現(xiàn)場離奇詭異刁笙,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評論 3 399
  • 文/潘曉璐 我一進店門采盒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蔚润,你說我怎么就攤上這事磅氨。” “怎么了嫡纠?”我有些...
    開封第一講書人閱讀 168,983評論 0 362
  • 文/不壞的土叔 我叫張陵烦租,是天一觀的道長。 經(jīng)常有香客問我除盏,道長叉橱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,938評論 1 299
  • 正文 為了忘掉前任者蠕,我火速辦了婚禮窃祝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘踱侣。我一直安慰自己粪小,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,955評論 6 398
  • 文/花漫 我一把揭開白布抡句。 她就那樣靜靜地躺著探膊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪待榔。 梳的紋絲不亂的頭發(fā)上逞壁,一...
    開封第一講書人閱讀 52,549評論 1 312
  • 那天,我揣著相機與錄音锐锣,去河邊找鬼腌闯。 笑死,一個胖子當(dāng)著我的面吹牛雕憔,可吹牛的內(nèi)容都是我干的绑嘹。 我是一名探鬼主播,決...
    沈念sama閱讀 41,063評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼橘茉,長吁一口氣:“原來是場噩夢啊……” “哼工腋!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起畅卓,我...
    開封第一講書人閱讀 39,991評論 0 277
  • 序言:老撾萬榮一對情侶失蹤擅腰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后翁潘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體趁冈,經(jīng)...
    沈念sama閱讀 46,522評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,604評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了渗勘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沐绒。...
    茶點故事閱讀 40,742評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖旺坠,靈堂內(nèi)的尸體忽然破棺而出乔遮,到底是詐尸還是另有隱情,我是刑警寧澤取刃,帶...
    沈念sama閱讀 36,413評論 5 351
  • 正文 年R本政府宣布蹋肮,位于F島的核電站,受9級特大地震影響璧疗,放射性物質(zhì)發(fā)生泄漏坯辩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,094評論 3 335
  • 文/蒙蒙 一崩侠、第九天 我趴在偏房一處隱蔽的房頂上張望漆魔。 院中可真熱鬧,春花似錦却音、人聲如沸有送。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雀摘。三九已至,卻和暖如春八拱,著一層夾襖步出監(jiān)牢的瞬間阵赠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評論 1 274
  • 我被黑心中介騙來泰國打工肌稻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留清蚀,地道東北人。 一個月前我還...
    沈念sama閱讀 49,159評論 3 378
  • 正文 我出身青樓爹谭,卻偏偏與公主長得像枷邪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子诺凡,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,747評論 2 361