C語言 檔案讀寫操作

2021-09-11 01:44:53 字數 4379 閱讀 5536

一、基本概念:

1、檔案流:

c 語言把檔案看作是乙個字元的序列,即檔案是由乙個乙個字元組成的字元流,因此 c 語言將檔案也稱之為檔案流。

即當讀寫乙個檔案時,可以不必關心檔案的格式或結構。

計算機檔案的儲存,物理上都是二進位制,所以文字檔案與二進位制檔案的區別並不是物理上的, 而是邏輯上的。這兩者只是在編碼層次上有差異。簡單來說,文字檔案是基於字元編碼的檔案,常見的編碼有 ascii 編碼,二進位制檔案是基於值編碼的檔案。

3、檔案緩衝:

檔案緩衝區(buffer) 存在的好處:首先,緩衝區在記憶體中,從記憶體中讀取資料比從檔案(硬碟)中讀取資料要快得多。

其次,對檔案的讀寫需要用到 fopen、fread、fwrite 等系統底層函式,而使用者程序每呼叫一次系統函式都要從使用者態切換到核心態,等執行完畢後再返回使用者態,這種切換要花費一定時間成本(對於高併發程式而言,這種狀態的切換會影響到程式效能)。

重新整理快取區:可以使用 fflush()。

二、檔案操作

1、檔案的開啟和關閉:

1)開啟fopen()      宣告 file * fopen ( const char * filename, const char * mode );

mode詳解:

2)關閉fclose()      宣告 int fclose ( file * stream );

成功返回0,失敗返回eof(-1)。

2、檔案的讀取和寫入(文字操作)

1)一次讀寫乙個字元

寫入 fputc()      宣告 int fputc (int ch, file * stream );      寫入成功返回寫入的字元,失敗返回eof。

讀取 fgetc()      宣告 int fgetc ( file * stream );                正常,返回讀取的字元;讀到檔案尾或出錯時,為 eof。

讀取字元,重點是判斷結束條件是什麼?通常的做法是依據返回值判斷。

2)一次讀寫一行字元

什麼是行: 

行是文字編輯器中的概念,檔案流中就是乙個字元,不同的平台有差異。

換行符在window 平台是'\r\n',在linux 平台是'\n'。

平台差異:

①linux 讀 windows 中的換行,會多讀乙個字元,windows 讀 linux 中的換行,則沒有問題。

解決:dos2unix 命令

②linux 中無論使用 gedit 還是 vim ,系統都會自動在末行新增\n 標誌。windows 當中系統不會自動新增\n。

寫入 fputcs()      宣告 int fputs(char *str,file *fp);          正常,返 0;出錯返 eof。

讀取 fgetcs()      宣告 char *fgets(char *str,int length,file *fp);   

正常,返 str 指標;出錯或遇到檔案結尾返空指標 null。

3、詳解 fgetcs() :

從 fp 所指向的檔案中,至多讀 length-1 個字元,送入字元陣列 str中, 如果在讀入 length-1 個字元結束前遇\n 或 eof,讀入即結束,字串讀入後在最後加乙個『\0』字元。

fgets 函式返回有三個條件:

1)讀 length-1 個字元前遇到\n,讀取結束(\n 被讀取) + \0。

2)讀 length-1 個字元前遇到 eof,讀取結束 +\0。

3)讀到length-1 個符 +\0。

4、檔案的讀寫(二進位制操作)----一次讀寫一塊資料

c 語言所有的檔案介面函式,要麼以 '\0',表示輸入結束,要麼以 '\n', eof(0xff)表示讀取結束,這些都是文字檔案的重要標識。而二進位制檔案,則往往以塊的形式,寫入或讀出。所有的二進位制介面對於這些標識,是不敏感的,把它們當做普通字元處理。

寫入 fwrite    宣告 int fwrite(void *buffer, int num_bytes, int count, file *fp);

讀取 fread    宣告int fread(void *buffer, int num_bytes, int count, file *fp);

返回值:   成功,返回讀/寫的字段數;出錯或檔案結束,返回 0。

注意 fread返回值陷阱:

#define _crt_secure_no_warnings

#include #include int main(void)

char *p = "123456789";

fwrite(p, 1, strlen(p), fpw);

rewind(fpw);

char buf[1024];

int n;

//錯誤讀法 4+4+0

n =fread((void*)buf,4,1,fpw);

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

n =fread((void*)buf,4,1,fpw);

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

n =fread((void*)buf,4,1,fpw); //按塊讀取,不夠4個導致出錯

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

//正確讀法 4+4+1

/*n = fread((void*)buf, 1, 4, fpw);

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

n = fread((void*)buf, 1, 4, fpw);

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

n = fread((void*)buf, 1, 4, fpw);

printf("n = %d\n", n);*/

return 0;

}

分析:fread  依靠讀出塊的多少來標識讀結果和檔案結束標誌。因此讀取時最好以最小的單元格式進行讀,或是以寫入的最小單元進行讀。

5、檔案指標偏移函式:

1、rewind()宣告 void rewind ( file * stream );      將檔案指標重新指向乙個流的開頭。

用途:如果乙個檔案具有讀寫屬性,則我們寫完檔案時,檔案指標指向結尾,當需要讀取時就需要 rewind函式。

2、ftell()宣告 long ftell ( file * stream );     

成功,返回當前讀寫位置偏離檔案頭部的位元組數。失敗, 返回-1。

3、fseek()宣告 int fseek ( file * stream, long offset, int where);      偏移檔案指標

成功返回 0 ,失敗返回-1。

常見起始位置巨集定義:

#define seek_set 0     //檔案開頭

#define seek_cur 1 //當前位置

#define seek_end 2 //檔案結尾

/*簡單用法*/

fseek(fp,100l,0); //把 fp 指標移動到離檔案開頭 100 位元組處;

fseek(fp,100l,1); //把 fp 指標移動到離檔案當前位置 100 位元組處;

fseek(fp,-100l,2); //把 fp 指標退回到離檔案結尾 100 位元組處。

三、總結:前面簡單介紹了文字讀寫和二進位制讀寫,但歸根到底二進位制讀寫才是本質。

1、使用二進位制讀取功能更加強大,比如讀取結構體就非常適合,結構體包含各種型別,型別大小不一,使用二進位制就不需要考慮這些問題。

2、檔案讀寫特別注意如何判斷是否讀取成功,是否寫入完成,一般使用返回值判斷。

3、讀以下檔案,請問 fgets 共執行了多少次?

fgets( buf, 10, fp) ;

1234567890abcdefg(換行)

1234567890(換行)

abcdefg(eof)

分析:fgets 共執行了5次,length為10,所以每次最多讀10-1 = 9個字元。

第一次,讀到1~9    +\0      第二次,讀到0~g  \n   +\0      第三次,讀到1~9    +\0

第四次,讀到0   \n   +\0     第五次,a~g    +\0

c語言檔案讀寫操作

檔案讀取操作 file fp char fname d printf s n fname fp fopen fname,r fscanf fp,d buf printf d buf 0 fclose fp fread,與fwrite是binary stream input output二進位製流的輸...

C語言檔案讀寫操作

標頭檔案 include include include include 用於生成隨機數 建立檔案指標 file fp 檢測檔案是否開啟成功 if fp fopen f52.txt w null 如果檔案不存在,則會新建。w 即設定操作為 write 寫操作 隨機的產生,設定時間種子 srand t...

C語言檔案操作 開 關 讀 寫

概述 1.乙個c檔案是乙個位元組流或二進位製流,它把資料看作是一連串的字元 位元組 而不考慮記錄的界限。在c語言中對檔案的訪問是以字元 位元組 為單位的。注 流式檔案 輸出時不會自動增加回車換行符以作為記錄結束的標誌,輸入時不以回車換行符作為記錄的間隔 2.ansi c標準使用緩衝檔案系統處理文字檔...