欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文帶你掌握C語言中的文件操作

 更新時間:2024年02月18日 10:19:29   作者:Betty’sSweet  
文件通常是駐留在外部介質(如磁盤等)上的,在使用時才調入內存中來,本文主要來和大家介紹一下C語言中的文件操作,有需要的可以了解下

1. 什么是文件

文件其實是指一組相關數據的有序集合。這個數據集有一個名稱,叫做文件名。文件通常是駐留在外部介質(如磁盤等)上的,在使用時才調入內存中來。

從文件功能上來講,一般可分為:程序文件數據文件

1.1 文件名

一個文件要有一個唯一的文件標識,以便用戶識別和引用,這就是文件名

  • ?件名包含3部分:?件路徑+?件名主?+?件后綴
  • 例如:c:\code\test.txt

1.2 程序文件

程序文件一般指:源程序文件(后綴為.c),目標文件(windows環(huán)境后綴為.obj),可執(zhí)行程序(windows環(huán)境后綴為.exe)

源程序文件一般在創(chuàng)建程序目錄文件下

源程序文件經過編譯器鏈接鏈接器鏈接可以生成我們的可執(zhí)行程序的文件。

1.3 數據文件

?件的內容不?定是程序,?是程序運行時讀寫的數據,?如程序運?需要從中讀取數據的?件,或者輸出內容的?件。

本章討論的是數據文件

以前各章所處理數據的輸?輸出都是以終端為對象的,即從終端的鍵盤輸?數據,運?結果顯?到顯?器上。

其實有時候我們會把信息輸出到磁盤上,當需要的時候再從磁盤上把數據讀取到內存中使?,這?處理的就是磁盤上?件。

2. 文件的作用

如果沒有?件,我們寫的程序的數據是存儲在電腦的內存中,如果程序退出,內存回收,數據就丟失了,等再次運?程序,是看不到上次程序的數據的,如果要將數據進?持久化的保存,我們就需要使?文件

3. 文件的打開與關閉

3.1 流與標準流

(1) 流

我們程序的數據需要輸出到各種外部設備,也需要從外部設備獲取數據,不同的外部設備的輸?輸出操作各不相同,為了?便程序員對各種設備進??便的操作,我們抽象出了的概念,我們可以把流想象成流淌著字符的河。

C程序針對文件、畫面、 鍵盤等的數據輸?輸出操作都是通過流操作的。?般情況下,我們要想向流?寫數據,或者從流中讀取數據,都是要打開流,然后操作。

(2) 標準流

那為什么我們從鍵盤輸?數據,向屏幕上輸出數據,并沒有打開流呢?那是因為C語?程序在啟動的時候,默認打開了3個流:

• stdin-標準輸?流,在?多數的環(huán)境中從鍵盤輸?,scanf函數就是從標準輸?流中讀取數據。

• stdout-標準輸出流,?多數的環(huán)境中輸出?顯?器界?,printf函數就是將信息輸出到標準輸出流中。

• stderr-標準錯誤流,?多數環(huán)境中輸出到顯?器界?。

這是默認打開了這三個流,我們使?scanf、printf等函數就可以直接進?輸?輸出操作的。stdin、stdout、stderr三個流的類型是: FILE*,通常稱為文件指針。

在C語?中,就是通過 FILE* 的?件指針來維護流的各種操作的。

3.2 文件指針

在緩沖文件系統中,關鍵的概念是“文件類型指針”,簡稱“文件指針”。

每個被使用的文件都在內存中開辟了一個相應的文件信息區(qū),用來存放文件的相關信息(如文件的名字,文件狀態(tài)及文件當前的位置等)。這些信息是保存在一個結構體變量中的。該結構體類型是有系統聲明的,取名【FILE】

例如,VS2022編譯環(huán)境提供的 stdio.h 頭文件中有以下的文件類型申明:

struct _iobuf {
        char *_ptr;
        int   _cnt;
        char *_base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char *_tmpfname;
       };
typedef struct _iobuf FILE;
FILE* pf;//文件指針變量

不同的C編譯器的FILE類型包含的內容不完全相同,但是大同小異。每當打開一個文件的時候,系統會根據文件的情況自動創(chuàng)建一個FILE結構的變量,并填充其中的信息,使用者不必關心細節(jié)。

一般都是通過一個FILE的指針來維護這個FILE結構的變量,這樣使用起來更加方便。我們來看看如何創(chuàng)建一個FILE的指針變量

FILE* pf;	//文件指針變量

定義pf是一個指向FILE類型數據的指針變量??梢允筽f指向某個文件的文件信息區(qū)(是一個結構體變量)。通過該文件信息區(qū)中的信息就能夠訪問該文件。也就是說,通過文件指針變量能夠找到與它關聯的文件,以此來進行相關操作。

3.3 文件的打開與關閉

?件在讀寫之前應該先打開?件,在使?結束之后應該關閉?件。這與我們前面學習的動態(tài)內存開辟很類似。

在編寫程序的時候,在打開?件的同時,都會返回?個FILE*的指針變量指向該?件,也相當于建?了指針和?件的關系。

ANSIC規(guī)定使? fopen 函數來打開?件, fclose 來關閉?件。

(1) fopen函數

頭文件#include<stdio.h>

聲明:FILE *fopen(const char *filename, const char *mode)

  • filename -- 字符串,表示要打開的文件名稱。
  • mode -- 字符串,表示文件的訪問模式。

作用:使用給定的模式 mode 打開 filename 所指向的文件

返回值:該函數返回一個 FILE 指針。否則返回 NULL,且設置全局變量 errno 來標識錯誤。

下表為常見的訪問模式(mode):

文件使用方式含義如果指定文件不存在
“r”(只讀)為了輸入數據,打開一個已經存在的文本文件出錯
“w”(只寫)為了輸出數據,打開一個文本文件建立一個新的文件
“a”(追加)向文本文件尾添加數據建立一個新的文件
rb”(只讀)為了輸入數據,打開一個二進制文件出錯
“wb”(只寫)為了輸出數據,打開一個二進制文件建立一個新的文件
“ab”(追加)向一個二進制文件尾添加數據出錯
“r+”(讀寫)為了讀和寫,打開一個文本文件出錯
“w+”(讀寫)為了讀和寫,建議一個新的文件建立一個新的文件
“a+”(讀寫)打開一個文件,在文件尾進行讀寫建立一個新的文件
“rb+”(讀寫)為了讀和寫打開一個二進制文件出錯
“wb+”(讀寫)為了讀和寫,新建一個新的二進制文件建立一個新的文件
“a+”(讀寫)打開一個二進制文件,在文件尾進行讀寫建立一個新的文件

(2) fclose函數

頭文件#include<stdio.h>

聲明:int fclose(FILE *stream)

stream -- 這是指向 FILE 對象的指針,該 FILE 對象指定了要被關閉的流。

作用:關閉流 stream。刷新所有的緩沖區(qū)

返回值:如果流成功關閉,則該方法返回零。如果失敗,則返回 EOF。

下列是fopen與fclose具體使用:

int main()
{
	//打開文件
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror(" fopen fail");
		return 1;
	}	
	//關閉文件
	fclose(pf);
	pf = NULL;		//防止野指針
	return 0;
}

4. 文件的順序讀寫

4.1 單字符輸入輸出

(1) fputc函數

頭文件:#include<stdio.h>

聲明:int fputc(int char, FILE *stream)

  • char -- 這是要被寫入的字符。該字符以其對應的 int 值進行傳遞。
  • stream -- 這是指向 FILE 對象的指針,該 FILE 對象標識了要被寫入字符的流。

作用:把參數 char 指定的字符(一個無符號字符)寫入到指定的流 stream 中。

返回值:如果沒有發(fā)生錯誤,則返回被寫入的字符。如果發(fā)生錯誤,則返回 EOF,并設置錯誤標識符。

下列是具體的fputc的使用方法:

#include<stdio.h>
int main()
{
	//打開文件
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror(" fopen fail");
		return 1;
	}
    //將abc放進文件
	fputc('a', pf);
	fputc('b', pf);
	fputc('c', pf);
	//關閉文件
	fclose(pf);
	pf = NULL;//防止野指針
	return 0;
}

如果你想查看寫入結果,可以在創(chuàng)建項目下找到Debug文件,打開

(2) fgetc函數

頭文件:#include<stdio.h>

聲明:int fgetc(FILE *stream)

  • stream -- 這是指向 FILE 對象的指針,該 FILE 對象標識了要在上面執(zhí)行操作的流。

作用:從指定的流 stream 獲取下一個字符(一個無符號字符)。

返回值:該函數以無符號 char 強制轉換為 int 的形式返回讀取的字符,如果到達文件末尾或發(fā)生讀錯誤,則返回 EOF。

下列是具體的fputc的使用方法:

#include<stdio.h>
int main()
{
	//打開文件
	FILE* pf = fopen("test.txt", "r");//只讀
	if (pf == NULL)
	{
		perror(" fopen fail");
		return 1;
	}
	fputc('a', pf);
	fputc('b', pf);
	fputc('c', pf);
	int ch = fgetc(pf);
	printf("讀出來的字符為:%c\n", ch);
	ch = fgetc(pf);
	printf("讀出來的字符為:%c\n", ch);
	ch = fgetc(pf);
	printf("讀出來的字符為:%c\n", ch);
	//關閉文件
	fclose(pf);
	pf = NULL;//防止野指針
	return 0;
}

輸出結果:

4.2 文本行輸入輸出

(1) fputs函數

頭文件:#include<stdio.h>

聲明:int fputs(const char *str, FILE *stream)

  • str -- 這是一個數組,包含了要寫入的以空字符終止的字符序列。
  • stream -- 這是指向 FILE 對象的指針,該 FILE 對象標識了要被寫入字符串的流。

作用:把字符串寫入到指定的流 stream 中,但不包括空字符。

返回值:該函數返回一個非負值,如果發(fā)生錯誤則返回 EOF。

下面是fputs的具體使用方法:

#include<stdio.h>
int main()
{
	//打開文件
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror(" fopen fail");
		return 1;
	}
	fputs("hello betty", pf);
	//關閉文件
	fclose(pf);
	pf = NULL;//防止野指針
	return 0;
}

演示結果:

(2) fgets函數

頭文件:#include<stdio.h>

聲明:char *fgets(char *str, int n, FILE *stream)

  • str -- 這是指向一個字符數組的指針,該數組存儲了要讀取的字符串。
  • n -- 這是要讀取的最大字符數(包括最后的空字符)。通常是使用以 str 傳遞的數組長度。
  • stream -- 這是指向 FILE 對象的指針,該 FILE 對象標識了要從中讀取字符的流。

作用:從指定的流 stream 讀取一行,并把它存儲在 str 所指向的字符串內。當讀取 (n-1) 個字符時,或者讀取到換行符時,或者到達文件末尾時,它會停止,具體視情況而定。

返回值:如果成功,該函數返回相同的 str 參數。如果到達文件末尾或者沒有讀取到任何字符,str 的內容保持不變,并返回一個空指針。如果發(fā)生錯誤,返回一個空指針。

下面是fgets的具體使用方法:

#include<stdio.h>
int main()
{
	//打開文件
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror(" fopen fail");
		return 1;
	}
	fputs("hello betty", pf);
	char arr[] = "##########";
	fgets(arr, 5, pf);
	puts(arr);
	//關閉文件
	fclose(pf);
	pf = NULL;//防止野指針
	return 0;
}

輸出結果:

雖然讀取五個字符,但是只會顯示四個字符,因為'\0也會默認添加進去

4.3 格式化輸入輸出

(1) fprintf函數

頭文件:#include<stdio.h>

聲明:int fprintf(FILE *stream, const char *format, ...)

  • stream -- 這是指向 FILE 對象的指針,該 FILE 對象標識了流。
  • format -- 這是 C 字符串,包含了要被寫入到流 stream 中的文本。它可以包含嵌入的 format 標簽,format 標簽可被隨后的附加參數中指定的值替換,并按需求進行格式化。

作用:按照一定格式向輸出流輸出數據。

返回值:如果成功,則返回寫入的字符總數,否則返回一個負數。

下面是fprintf的具體使用方法:

typedef struct student {
	char name[20];
	int height;
	float score;
}stu;
int main()
{
	stu s = { "beidi", 170, 95.0 };
	//寫文件
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror(" fopen fail");
		return 1;
	}
	fprintf(pf, "%s %d %f", s.name, s.height, s.score);
	//關閉文件
	fclose(pf);
	pf = NULL;//防止野指針
	return 0;
}

(2) fscanf函數

頭文件:#include<stdio.h>

聲明:int fscanf(FILE *stream, const char *format, ...)

  • stream -- 這是指向 FILE 對象的指針,該 FILE 對象標識了流。
  • format -- 這是 C 字符串,包含了以下各項中的一個或多個:空格字符非空格字符和 format說明符。

作用:按照一定格式從輸入流輸入數據。

返回值:如果成功,該函數返回成功匹配和賦值的個數。如果到達文件末尾或發(fā)生讀錯誤,則返回 EOF。

下面是fscanf的具體使用方法:

typedef struct student {
	char name[20];
	int height;
	float score;
}stu;
int main()
{
	stu s = { "beidi", 170, 95.0 };
	//寫文件
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror(" fopen fail");
		return 1;
	}
	fscanf(pf, "%s %d %f", s.name, &(s.height), &(s.score));
	printf("%s %d %f", s.name, s.height, s.score);
	//關閉文件
	fclose(pf);
	pf = NULL;//防止野指針
	return 0;
}

4.4 二進制輸入輸出

(1) fwrite函數

頭文件:#include<stdio.h>

聲明:size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)

  • ptr -- 這是指向要被寫入的元素數組的指針。
  • size -- 這是要被寫入的每個元素的大小,以字節(jié)為單位。
  • nmemb -- 這是元素的個數,每個元素的大小為 size 字節(jié)。
  • stream -- 這是指向 FILE 對象的指針,該 FILE 對象指定了一個輸出流。

作用:把 ptr 所指向的數組中的數據寫入到給定流 stream 中。

返回值:如果成功,該函數返回一個 size_t 對象,表示元素的總數,該對象是一個整型數據類型。如果該數字與 nmemb 參數不同,則會顯示一個錯誤。

下面是fwrite的具體使用方法:

typedef struct student {
	char name[20];
	int height;
	float score;
}stu;
int main()
{
	stu s = { "beidi", 170, 95.0 };
	//寫文件
	FILE* pf = fopen("test.txt", "wb");//二進制寫入
	if (pf == NULL)
	{
		perror(" fopen fail");
		return 1;
	}
	fwrite(&s, sizeof(s), 1, pf);
	//關閉文件
	fclose(pf);
	pf = NULL;//防止野指針
	return 0;
}

二進制數據正常人是無法看懂的,但是電腦能準確識別

(2) fread函數

頭文件:#include<stdio.h>

聲明:size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)

  • ptr -- 這是指向帶有最小尺寸 size*nmemb 字節(jié)的內存塊的指針。
  • size -- 這是要讀取的每個元素的大小,以字節(jié)為單位。
  • nmemb -- 這是元素的個數,每個元素的大小為 size 字節(jié)。
  • stream -- 這是指向 FILE 對象的指針,該 FILE 對象指定了一個輸入流。

作用:從給定流 stream 讀取數據到 ptr 所指向的數組中

返回值:成功讀取的元素總數會以 size_t 對象返回,size_t 對象是一個整型數據類型。如果總數與 nmemb 參數不同,則可能發(fā)生了一個錯誤或者到達了文件末尾。

下面是fread的具體使用方法

typedef struct student {
	char name[20];
	int height;
	float score;
}stu;
int main()
{
	stu s = {0};
	//寫文件
	FILE* pf = fopen("test.txt", "rb");//二進制寫出
	if (pf == NULL)
	{
		perror(" fopen fail");
		return 1;
	}
	fread(&s, sizeof(s), 1, pf);
	printf("%s %d %f", s.name, s. height, s.score);
	//關閉文件
	fclose(pf);
	pf = NULL;//防止野指針
	return 0;
}

4.5 流輸入輸出

從前面我們知道在我們輸入輸出時,默認打開**stdin - 標準輸入流 **, stdout - 標準輸出流, **stderr - 標準輸錯誤 **。那我們可不可以利用流來輸入輸出呢?答案自然是可以的,下面是具體實例:

int main()
{
	printf("輸入前:");
	int ch = fgetc(stdin);//輸入
	printf("輸入后:");
	fputc(ch, stdout);//輸出
	return 0;
}

還有另外一種方法:

int main()
{
	printf("輸入前:");
	int ch = 0;
	fscanf(stdin, "%c", &ch);
	printf("輸入后:");
	fprintf(stdout, "%c", ch);
	return 0;
}

4.6 補充

(1) sprintf與sscanf

頭文件:#include<stdio.h>

聲明:int sprintf(char *str, const char *format, ...)

  • str -- 這是指向一個字符數組的指針,該數組存儲了 C 字符串。
  • format -- 這是字符串,包含了要被寫入到字符串 str 的文本。它可以包含嵌入的 format 標簽,format 標簽可被隨后的附加參數中指定的值替換,并按需求進行格式化

作用:將格式化數據轉換為字符串

返回值:如果成功,則返回寫入的字符總數,不包括字符串追加在字符串末尾的空字符。如果失敗,則返回一個負數。

頭文件:#include<stdio.h>

聲明:int sscanf(const char *str, const char *format, ...)

  • str -- 這是 C 字符串,是函數檢索數據的源。
  • format -- 這是 C 字符串,包含了以下各項中的一個或多個:空格字符、非空格字符和 format說明符。

作用:將字符串按照一定格式轉換為格式化數據

返回值:如果成功,該函數返回成功匹配和賦值的個數。如果到達文件末尾或發(fā)生讀錯誤,則返回 EOF。

下列展示了sprintf與sscanf的具體用法:

typedef struct student {
	char name[20];
	int height;
	float score;
}stu;

int main()
{
	char buf[100] = { 0 };
	stu s = { "betty", 170, 95.0f };
	stu tmp = { 0 };
	//將這個結構體的成員轉化為字符串
	sprintf(buf, "%s %d %f", s.name, s.height, s.score);
	printf("%s\n", buf);
	//將這個字符串中內容還原為一個結構體數據呢
	sscanf(buf, "%s %d %f", tmp.name, &(tmp.height), &(tmp.score));
	printf("%s %d %f", tmp.name, tmp.height, tmp.score);
	return 0;
}

(2) 對比

下表展示了scanf與printf,fscanf與fprintf,sscanf與sprintf之間的區(qū)別

函數功能
scanf針對標準輸入(鍵盤)的格式化輸入函數
printf針對標準輸入出(屏幕)的格式化輸出函數
fscanf針對所以輸入流的格式化輸入函數
fprintf針對所以輸出流的格式化輸出函數
sscanf從一個字符串中讀取一個格式化數據
sprintf把一個格式化數據轉換為字符串

5. 文本文件和二進制文件

根據數據的組織形式,數據?件被稱為?本?件或者二進制?件。

  • 文本文件:以ASCII字符的形式存儲的?件
  • 二進制文件:數據在內存中以?進制的形式存儲的文件

?個數據在?件中是怎么存儲的呢?字符?律以ASCII形式存儲,數值型數據既可以?ASCII形式存儲,也可以使??進制形式存儲。

如有整數10000,如果以ASCII碼的形式輸出到磁盤,則磁盤中占?5個字節(jié)(每個字符?個字節(jié)),??進制形式輸出,則在磁盤上只占4個字節(jié)。

字符1的二進制序列:00110001,字符0的二進制序列:00110000

測試代碼:

int main()
{
	int a = 10000;
	FILE* pf = fopen("test.txt", "wb");
	fwrite(&a, 4, 1, pf);//二進制的形式寫到文件中
	fclose(pf);
	pf = NULL;
	return 0;
}

右擊源文件,添加現有項,將test.txt添加進入

右擊test.txt文件,選擇打開方式,選擇二進制編輯器

10 27 00 00便是10000以小端存儲的十六進制形式。

6. 文件的隨機讀寫

6.1 fseek函數

頭文件:#include<stdio.h>

聲明:int fseek(FILE *stream, long int offset, int whence)

  • stream -- 這是指向 FILE 對象的指針,該 FILE 對象標識了流。
  • offset -- 這是相對 whence 的偏移量,以字節(jié)為單位。
  • whence -- 這是表示開始添加偏移 offset 的位置。

作用:設置流 stream 的文件位置為給定的偏移 offset,參數 offset 意味著從給定的 whence 位置查找的字節(jié)數。

返回值:如果成功,則該函數返回零,否則返回非零值。

whence偏移offset的三種位置:

常量描述
SEEK_SET文件的開頭
SEEK_CUR文件指針的當前位置
SEEK_END文件的末尾

假設文件中放的是字符串“abcdef,下面是fseek的具體使用實例:

int main()
{
	//打開文件
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror(" fopen fail");
		return 1;
	}
	fseek(pf, 4, SEEK_SET);
	//從其實位置偏移四個字節(jié)
	int ch1 = fgetc(pf);
	printf("%c ", ch1);
	fseek(pf, -3, SEEK_END);
	//從結束位置偏移七個個字節(jié)
         int ch2 = fgetc(pf);
	printf("%c ", ch2);
	fseek(pf, 1, SEEK_CUR);
	//從當前位置偏移一個字節(jié)
	int ch3 = fgetc(pf);
	printf("%c ", ch3);
	//關閉文件
	fclose(pf);
	pf = NULL;//防止野指針
	return 0;
}

  • 從起始位置偏移四個字節(jié),輸出e。
  • 從末尾偏移三個字節(jié),輸出d。
  • 此時偏移指向e的位置,再偏移一個字節(jié)指向f。

6.2 ftell函數

頭文件:#include<stdio.h>

聲明:long int ftell(FILE *stream)

stream -- 這是指向 FILE 對象的指針,該 FILE 對象標識了流。

作用:返回?件指針相對于起始位置的偏移量

返回值:該函數返回位置標識符的當前值。如果發(fā)生錯誤,則返回 -1L,全局變量 errno 被設置為一個正值。

我們可以利用fseek和ftell來計算文件的長度(不包含'\0'),下列是代碼示例

int main()
{
	FILE* pFile;
	long size;
	pFile = fopen("test.txt", "rb");
	if (pFile == NULL) 
		perror("Error opening file");
	else
	{
		fseek(pFile, 0, SEEK_END); //non-portable
		size = ftell(pFile);
		fclose(pFile);
		printf("文件長度為: %ld bytes.\n", size);
	}
	return 0;
}

6.3 rewind函數

頭文件:#include<stdio.h>

聲明:void rewind(FILE *stream)

stream -- 這是指向 FILE 對象的指針,該 FILE 對象標識了流

作用:讓?件指針的位置回到?件的起始位置

返回值:該函數不返回任何值。

rewind常常在文件讀與寫同時使用時,以方便文件讀取。下面是rewind的具體使用實例:

#include <stdio.h>
int main()
{
	int n;
	FILE* pFile;
	char buffer[27];
	pFile = fopen("myfile.txt", "w+");
	for (n = 'A'; n <= 'Z'; n++)
		fputc(n, pFile);//放入26個字母
	rewind(pFile);//回到起始位置,方便讀取
	fread(buffer, 1, 26, pFile);//讀取·
	fclose(pFile);
	buffer[26] = '\0';//字符串的結束標識
	printf(buffer);
	return 0;
}

7. ?件讀取結束的判定

7.1 被錯誤使用的 feof

在我們學習C語言文件操作的過程中,常常會有人誤認為feof是判斷文件是否結束的函數,其實這并不準確。feof 的作?是:當?件讀取結束的時候,判斷是讀取結束的原因是:遇到?件尾結束還是文件讀取失敗結束。

7.2 常見的結束標志

函數結束標志
fgetc如果讀取正常,返回讀取到的字符的ASCLL碼值 如果讀取失敗,返回EOF
fgets如果讀取正常,返回讀取到的數據的地址 如果讀取失敗,返回NULL
fscanf如果讀取正常,返回的是格式串中指定的數據個數 如果讀取失敗,返回的是小于格式串中指定的數據個數
fread如果讀取正常,返回的是等于要讀取的數據個數 如果讀取失敗,返回的是小于要讀取的數據個數

8. 文件緩沖區(qū)

ANSIC 標準采用緩沖文件系統處理的數據文件的,所謂緩沖文件系統是指系統自動地在內存中為程序中每一個正在使用的文件開辟一塊“文件緩沖區(qū)”。

  • 從內存向磁盤輸出數據會先送到內存中的緩沖區(qū),裝滿緩沖區(qū)后才?起送到磁盤上。
  • 如果從磁盤向計算機讀?數據,則從磁盤?件中讀取數據輸?到內存緩沖區(qū)(充滿緩沖區(qū)),然后再從緩沖區(qū)逐個地將數據送到程序數據區(qū)(程序變量等)
  • 緩沖區(qū)的??根據C編譯系統決定的。

我們可以利用下列代碼證明緩沖區(qū)的存在:

include <stdio.h>
#include <windows.h>
//VS2019 WIN11環(huán)境測試
int main()
{
	FILE* pf = fopen("test.txt", "w");
	fputs("abcdef", pf); //先將代碼放在輸出緩沖區(qū)
	printf("睡眠10秒-已經寫數據了,打開test.txt?件,發(fā)現?件沒有內容\n");
	Sleep(10000);
	printf("刷新緩沖區(qū)\n");
	fflush(pf); //刷新緩沖區(qū)時,才將輸出緩沖區(qū)的數據寫到?件(磁盤)
	//注:fflush 在?版本的VS上不能使?了
	printf("再睡眠10秒-此時,再次打開test.txt?件,?件有內容了\n");
	Sleep(10000);
	fclose(pf);
	//注:fclose在關閉?件的時候,也會刷新緩沖區(qū)
	pf = NULL;
	return 0;
}

刷新緩沖區(qū)前:

刷新緩沖區(qū)后:

因為有緩沖區(qū)的存在,C語?在操作?件的時候,需要做刷新緩沖區(qū)或者在?件操作結束的時候關閉?件。如果不做,可能導致讀寫?件的問題。

以上就是一文帶你掌握C語言中的文件操作的詳細內容,更多關于C語言文件操作的資料請關注腳本之家其它相關文章!

相關文章

最新評論