C語言文件

[TOC]

UNIX的哲學(xué),萬物皆文件.

打開關(guān)閉文件

FILE * fopen(const char *filename,const char * type);

系統(tǒng)調(diào)用fopen()打開文件:給用戶指定的文件在內(nèi)存中分配一個FILE結(jié)構(gòu),并將結(jié)構(gòu)返回給用戶程序,以后用戶就可以更具FILE指針來實現(xiàn)對文件的存取操作了.當使用打開函數(shù)時必須給出文件名和操作方式.如果文件名不存在,就意味著創(chuàng)建文件,并將FILE *指針指向該文件.如果存在就意味著刪除該文件.

FILE 結(jié)構(gòu)體如下

typedef struct __sFILE {
    unsigned char *_p;  /* current position in (some) buffer */
    int _r;     /* read space left for getc() */
    int _w;     /* write space left for putc() */
    short   _flags;     /* flags, below; this FILE is free if 0 */
    short   _file;      /* fileno, if Unix descriptor, else -1 */
    struct  __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */
    int _lbfsize;   /* 0 or -_bf._size, for inline putc */

    /* operations */
    void    *_cookie;   /* cookie passed to io functions */
    int (* _Nullable _close)(void *);
    int (* _Nullable _read) (void *, char *, int);
    fpos_t  (* _Nullable _seek) (void *, fpos_t, int);
    int (* _Nullable _write)(void *, const char *, int);

    /* separate buffer for long sequences of ungetc() */
    struct  __sbuf _ub; /* ungetc buffer */
    struct __sFILEX *_extra; /* additions to FILE to not break ABI */
    int _ur;        /* saved _r when _r is counting ungetc data */

    /* tricks to meet minimum requirements even when malloc() fails */
    unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */
    unsigned char _nbuf[1]; /* guarantee a getc() buffer */

    /* separate buffer for fgetln() when line crosses buffer boundary */
    struct  __sbuf _lb; /* buffer for fgetln() */

    /* Unix stdio files get aligned to block boundaries on fseek() */
    int _blksize;   /* stat.st_blksize (may be != _bf._size) */
    fpos_t  _offset;    /* current lseek offset (see WARNING) */
} FILE;

1.對于mode有常見的方式

mode description
r (read) 以只讀方式打開文件.該文件必須存在;
w (write) 只寫的方式.若文件存在原有的內(nèi)容會被清除;若文件不存在,創(chuàng)建文件;
a (append) 追加方式打開只寫文件,只允許進行寫操作.文件存在,則添加內(nèi)容在文件末尾;文件不存在則創(chuàng)建文件 (EOF符保留)
+ (read and write) 可讀可寫
b (binary) 以二進制方式打開文件
t (text) 以文本方式打開文件(默認以該模式打開文件)

2.常見的組合方式

composed mode description
r+ 以讀寫的方式操作文件,允許讀寫.文件必須存在,否則返回NULL.打開成功返回指向文件的指針,指向文件的頭部 (注意很多書上或資料上講述追加方式打開成功后位置指針指向文件末尾是錯誤的);
rb+ 以可讀可寫,二進制方式打開文件,允許讀寫.文件必須存在,否則返回NULL.若打開文件成功返回文件指針,指向文件頭部;
rt+ 以可讀可寫,文本方式打開文件,允許讀寫.文件必須存在,否則返回NULL.若打開文件成功,返回文件指針,指向文件頭部;
w 以只寫的方式打開文件拄轻,只允許寫滑频,若文件存在,文件中原有內(nèi)容會被清除;若文件不存在,則創(chuàng)建文件钾虐,打開成功后返回文件指針,位置指針指向文件頭部
w+ 以讀寫的方式打開文件,允許讀寫庆冕,若文件存在,文件中原有內(nèi)容會被清除劈榨;若文件不存在访递,則創(chuàng)建文件,打開成功后返回文件指針鞋既,位置指針指向文件頭部
a 以追加只寫的方式打開文件,只允許寫.若文件存在,則追加的內(nèi)容在文件的末尾,若文件不存在則創(chuàng)建文件.打開成功后返回文件的指針,指向文件的頭部.
a+ 以追加力九、可讀寫的方式打開文件耍铜,允許讀寫邑闺。若進行讀操作,則從頭開始讀棕兼;若進行寫操作陡舅,則將內(nèi)容添加在末尾。若文件不存在伴挚,則創(chuàng)建文件靶衍。打開成功后返回文件指針,位置指針指向文件頭部(不保留EOF)

二進制和文本打開方式基本相同,不同的地方是讀取文本是碰到ASCII碼為26的字符是,則會停止文件的讀寫,默認文件以及結(jié)束.應(yīng)為正常的文本不會有ASCII碼26的字符.而二進制打開方式不存在這個問題.(UNIX下沒有區(qū)別);

注意:

1)在以追加方式打開文件時茎芋,位置指針指向文件的首部颅眶。

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

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

? 位置指針:對文件進行讀寫操作時移動的指針

? 在頭文件<stdio.h>中存在一個結(jié)構(gòu)體_iobuf,在VC6.0中選中FILE田弥,然后F12涛酗,則可以看到_iobuf的具體定義(UNIX 的大致相同):

struct _iobuf
{
        char *_ptr;               // 指向buffer中第一個未讀的字節(jié)       
        int   _cnt;                 // 記錄剩余未讀字節(jié)的個數(shù)
        char *_base;           // 指向一個字符數(shù)組,即這個文件的緩沖
        int   _flag;                // FILE結(jié)構(gòu)所代表的打開文件的一些屬性
        int   _file;                 // 用于獲取文件描述偷厦,可以使用fileno函數(shù)獲得此文件的句柄商叹。
        int   _charbuf;          // 單字節(jié)的緩沖,即緩沖大小僅為1個字節(jié)只泼,如果為單字節(jié)緩沖剖笙,_base將無效
        int   _bufsiz;            // 記錄這個緩沖的大小
        char *_tmpfname;    // temporary file (i.e., one created by tmpfile()
                                        // call). delete, if necessary (don't have to on
                                        // Windows NT because it was done by the system when
                                        // the handle was closed). also, free up the heap
                                        // block holding the pathname.
};
typedef struct _iobuf FILE;

? 比如用FILE *fp定義了一個文件指針,并成功打開一個文件之后请唱,fp只是指向該結(jié)構(gòu)體弥咪,而在對文件進行讀寫操作時过蹂,fp的值并不會改變,改變的是結(jié)構(gòu)體中_ptr的值聚至,這個_ptr就是位置指針榴啸。

? 2)以追加方式打開時,若進行寫操作晚岭,則rewind函數(shù)和fseek函數(shù)不會起到作用鸥印,因為以追加方式打開時進行寫操作的話,系統(tǒng)會自動將位置指針移動到末尾坦报。

? 3)當文件打開用于更新時库说,可以通過文件指針對文件進行讀寫操作,但是如果沒有給出fseek或者rewind的話片择,讀操作后面不能直接跟寫操作潜的,否則會是無效的寫操作(位置指針會移動,但是需要寫入文件的內(nèi)容不會被寫入到文件當中)字管,但是寫操作后可以直接跟讀操作啰挪。

每次調(diào)用fopen()打開文件后都要記得調(diào)用fclose()關(guān)閉文件

C語言提供了以下幾種文件讀寫方式

1.字符讀寫: fgetc()/fputc() (讀/寫);

fgetc()函數(shù):

(1)一般調(diào)用形式: char ch = fgetc(fd);

(2)作用: 文件中讀取一個字符;

(3)返回值:

? 成功:返回值所得到的字符;
? 失敵笆濉:返回EOF(-1)亡呵。

*注意問的打開方式

fputc()函數(shù):

(1)一般調(diào)用形式: char res = fputc(fd,ch);

(2)作用: 文件中寫入一個字符;

(3)返回值

? 成功:函數(shù)輸入的字符;
? 失斄蚋辍:返回EOF(-1)锰什。

說明:函數(shù)putchar()是在stdio.h中用預(yù)處理命令定義的宏,即:

//define putchar(c) fputc(c,stdout)

char a = 'a';
char ch = fgetc(fd);
char res = fputc(a, fd);

字符串讀寫: fgets()/fputs() (讀/寫);

1.fgets()函數(shù):

  • 一般調(diào)用形式:char * fgets(char *str ,int num ,FILE *fd); (fd 的mode rt)

    參數(shù)說明: str 保存從文件中讀取的字符串;
    ? num 從文件中讀取的字符串中字符個數(shù)不超過num-1.在讀入最后一個字符后加上串結(jié)束標志'\0';

  • 返回值:
    成功: 返的字符串;

    失敗: 返回NULL

    ?

2.fputs() 文件中寫入字符串

  • 一般調(diào)用形式: int num = fputs(char *s,FILE *fd); (fd 的mode at+)

    s 要寫入的字符串;

    fd 待寫入的文件;

    返回值:

    ? 成功: 寫入的字符個數(shù)num;

    ? 失敗: EOF(-1);

int res = fputs("test", fd);
    
char rs[11];
char *r = fgets(rs, 11, fd);

數(shù)據(jù)塊讀寫: fwrite()/fread() (讀/寫)

  • 一般調(diào)用形式:

    size_t fwrite(void *buffer,size_t size ,size_t count, FILE *fd);

    size_t fread(void *buffer,size_t size, size_t count ,FILE *fd);

  • 參數(shù)說明:

    buffer: 緩沖區(qū)指針.對fread,它是暫存讀入數(shù)據(jù)的指針;對fwrite,它是要輸出數(shù)據(jù)的指針;
    size: 要讀寫的字節(jié)數(shù);
    count: 要進行讀寫多少個size字節(jié)的數(shù)據(jù)項;
    fd: 待讀寫的文件指針;

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

struct stu{
    int age;
    int num;
    char name[10];
    char addr[20];
}boya[2],boyb[2],*qq,*pp;
int main() {
    FILE *fd;
    char ch;
    int i;
    qq = boya;
    pp = boyb;
    if ((fd = fopen("/Users/sks/Desktop/stu_list", "wb+")) == NULL) {
        printf("Cannot open file. Strike any key to exit!");
        getchar();
        exit(1);
    }
    printf("intput data\n");
    for (i=0; i<2; i++,qq++) {
        scanf("%d%d%s%s",&qq->age,&qq->num,qq->name,qq->addr);
    }
    qq = boya;
    size_t writeSize = fwrite(qq, sizeof(struct stu), 2, fd);
    rewind(fd);
    size_t readSize = fread(pp, sizeof(struct stu), 2, fd);
    
    printf("\n\nname\tnumber      age      addr\n");
    for (i=0; i<2; i++,pp++) {
        printf("%s   %d   %d   %s\n",pp->name,pp->num,pp->age,pp->addr);
    }
    fclose(fd);
    return 0;
}

本例程序定義了一個結(jié)構(gòu)stu丁逝,說明了兩個結(jié)構(gòu)數(shù)組boya和boyb以及兩個結(jié)構(gòu)指針變量pp和qq汁胆。pp指向boya,qq指向boyb霜幼。程序第14行以讀寫方式打開二進制文件“stu_list”嫩码,輸入二個學(xué)生數(shù)據(jù)之后,寫入該文件中罪既,然后把文件內(nèi)部位置指針移到文件首铸题,讀出兩塊學(xué)生數(shù)據(jù)后,在屏幕上顯示萝衩。

格式化讀寫: fscanf()/fprintf() (寫/讀);

一般調(diào)用形式:

? (1)int fprintf(FILE *stream,const char *format,[argument]…) 輸出格式化字符串或者將格式化字符串輸出到流 (文件);

? (2)int fscanf(FILE *stream, const char *) 輸入文件中的內(nèi)容到某個變量中.

? fscanf(fd,"%s",res)

返回值:

? 成功:

? fprintf讀取的字符個數(shù);

? fscanf: 返回1

? 失敗:

? EOF;

int res = fprintf(fd, "%s",s);
    if (res == EOF) {
        printf("輸入失敗\n");
    }
    
    char tmp[26];
//
   int len = fscanf(fd, "%s\n",tmp);

?

其他文件相關(guān)操作

ftell()函數(shù): 得到流式文件的當前讀寫位置,返回流式文件當前讀寫位置距離文件頭部的字節(jié)數(shù).

long     ftell(FILE *);

fseek(): 把fd 的文件讀寫位置指針移動到知道的位置;

@param FILE* 待操作的文件指針
@param long  距離起始點的位置
@parma int   計算的起始點
@return  0 success 文件位置指針指向正確的offset,錯誤返回-1
/*
    有三類起始點
    SEEK_SET 0   文件開頭
    SEEK_CUR 1   文件當前位置
    SEEK_END 2   文件末尾
*/
int  fseek(FILE *, long offset, int origin);

rewind(): 將文件位置指針重新指向一個文件流的開頭

void     rewind(FILE *);

eg:

long fileLength = 0; 
fseek(fd, 0, SEEK_END);
fileLength = ftell(fd);
rewind(fd);

fflush():清空緩存

所謂flush一個緩沖回挽,是指對寫緩沖而言,將緩沖內(nèi)的數(shù)據(jù)全部寫入實際的文件猩谊,并將緩沖清空千劈,這樣可以保證文件處于最新的狀態(tài)。之所以需要flush牌捷,是因為寫緩沖使得文件處于一種不同步的狀態(tài)墙牌,邏輯上一些數(shù)據(jù)已經(jīng)寫入了文件涡驮,但實際上這些數(shù)據(jù)仍然在緩沖中,如果此時程序意外地退出(發(fā)生異诚脖酰或斷電等)捉捅,那么緩沖里的數(shù)據(jù)將沒有機會寫入文件。flush可以在一定程度上避免這樣的情況發(fā)生虽风。

在這個表中我們還能看到C語言支持兩種緩沖棒口,即行緩沖(Line Buffer)和全緩沖(Full Buffer)。全緩沖是經(jīng)典的緩沖形式辜膝,除了用戶手動調(diào)用fflush外无牵,僅當緩沖滿的時候,緩沖才會被自動flush掉厂抖。而行緩沖則比較特殊茎毁,這種緩沖僅用于文本文件,在輸入輸出遇到一個換行符時忱辅,緩沖就會被自動flush七蜘,因此叫行緩沖。

 FILE *fd;
    if ((fd = fopen("/Users/sks/Desktop/ch.txt", "w")) == NULL) {
        printf("Open file failed.Press any key to exit!");
        getchar();
        exit(1);
    }
    
    Student stu;
    stu.number = 10000;
//    stu.name = "guohuabing";
    strcpy(stu.name, "guohuabing");
    fflush(fd);
    fwrite(&stu, sizeof(struct SStudent), 1, fd);
    fclose(fd);

socket 通信和文件操作的關(guān)系

待續(xù)....

C語言文件操作和操作系統(tǒng)文件子系統(tǒng)的關(guān)系

參考:

? http://www.2cto.com/kf/201207/143344.html

? http://www.cnblogs.com/L-hq815/archive/2012/06/30/2571066.html

? http://www.cnblogs.com/dolphin0520/archive/2011/10/05/2199598.html

? http://c.biancheng.net/cpp/html/107.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末墙懂,一起剝皮案震驚了整個濱河市橡卤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌垒在,老刑警劉巖蒜魄,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扔亥,死亡現(xiàn)場離奇詭異场躯,居然都是意外死亡,警方通過查閱死者的電腦和手機旅挤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進店門踢关,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人粘茄,你說我怎么就攤上這事签舞。” “怎么了柒瓣?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵儒搭,是天一觀的道長。 經(jīng)常有香客問我芙贫,道長搂鲫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任磺平,我火速辦了婚禮魂仍,結(jié)果婚禮上拐辽,老公的妹妹穿的比我還像新娘。我一直安慰自己俱诸,他們只是感情好,可當我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布睁搭。 她就那樣靜靜地躺著笼平,像睡著了一般。 火紅的嫁衣襯著肌膚如雪遇伞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天鸠珠,我揣著相機與錄音秋麸,去河邊找鬼。 笑死灸蟆,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的可缚。 我是一名探鬼主播斋枢,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瓤帚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起轩勘,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤怯邪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體榛斯,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年懂缕,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搪柑。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡索烹,死狀恐怖工碾,靈堂內(nèi)的尸體忽然破棺而出百姓,到底是詐尸還是另有隱情,我是刑警寧澤垒拢,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站求类,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏尸疆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一犯眠、第九天 我趴在偏房一處隱蔽的房頂上張望脖捻。 院中可真熱鬧,春花似錦地沮、人聲如沸羡亩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至楷怒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鸠删,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工巧娱, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留烘贴,地道東北人禁添。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓老翘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親锻离。 傳聞我的和親對象是個殘疾皇子酪捡,可洞房花燭夜當晚...
    茶點故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 語言中對文件進行操作必須首先打開文件,打開文件主要涉及到fopen函數(shù)纳账。fopen函數(shù)的原型為 FILE* fop...
    朱森閱讀 801評論 0 1
  • 文件指針 FILE * 指針變量標識符作用:通過該指針即可找到存放某個文件信息的結(jié)構(gòu)變量,然后按結(jié)構(gòu)變量提供的信息...
    永斷閻羅閱讀 457評論 0 3
  • 所謂“文件”是指一組相關(guān)數(shù)據(jù)的有序集合疏虫,該數(shù)據(jù)的集合的名字就是文件名永罚。文件可以分為很多類卧秘,如源程序文件呢袱、目標文件、...
    一葉之界閱讀 476評論 0 0
  • c語言里面的各種字符/字符串讀寫一直搞得我分不清楚翅敌。羞福。今天來學(xué)習(xí)總結(jié)一下:原文章來自http://www.cnbl...
    AwesomeAshe閱讀 470評論 0 0
  • Android NDK開發(fā)之旅 目錄 文件讀寫 一個文件蚯涮,無論它是文本文件還是二進制文件治专,都是代表了一系列的字節(jié)。...
    香沙小熊閱讀 4,617評論 0 4