欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報邀請碼778899分享:開發(fā)語言 C語言:文件操作

柚子快報邀請碼778899分享:開發(fā)語言 C語言:文件操作

http://yzkb.51969.com/

目錄

?

為什么使用文件

什么是文件?

程序文件

數(shù)據(jù)?件

文件名

二進制文件和文本文件

文件的打開和關(guān)閉

流和標準流、

標準流

文件指針

文件的打開和關(guān)閉

文件打開方式

文件的順序讀寫

fputc函數(shù)示范(寫字符)

fgetc函數(shù)示范(讀字符)

(字符)stdin標準輸入流和stdout標準輸出流

fputs函數(shù)的示范(寫字符串)

fgets函數(shù)示范(讀字符串)

(字符串)stdin標準輸入流和stdout標準輸出流

fprintf(寫整數(shù),浮點數(shù),字符,字符串)

fscanf(讀整數(shù),浮點數(shù),字符,字符串)

(整數(shù),浮點數(shù),字符,字符串)stdin標準輸入流和stdout標準輸出流

對比一組函數(shù):

fwrite函數(shù)

fread函數(shù)

文件的隨機讀寫

fseek

從文件開頭向后偏移

從光標位置偏移

文件末尾向前面偏移

ftell函數(shù)

?rewind函數(shù)

?件讀取結(jié)束的判定

拷貝字符串代碼

文件緩沖區(qū)

為什么使用文件

如果沒有?件,我們寫的程序的數(shù)據(jù)是存儲在電腦的內(nèi)存中,如果程序退出,內(nèi)存回收,數(shù)據(jù)就丟失了,等再次運?程序,是看不到上次程序的數(shù)據(jù)的,如果要將數(shù)據(jù)進?持久化的保存,我們可以使??件,因為文件是存放在硬盤上的

什么是文件?

磁盤上的?件和文件夾都是?件。 但是在程序設(shè)計中,我們?般談的?件有兩種:程序?件、數(shù)據(jù)?件(從?件功能的?度來分類 的)。

程序文件

程序?件包括源程序?件(后綴為.c),

?標?件(windows環(huán)境后綴為.obj),

可執(zhí)?程序(windows環(huán)境后綴為.exe)。

程序文件

目標文件

可執(zhí)行程序

數(shù)據(jù)?件

?件的內(nèi)容不?定是程序,?是程序運?時讀寫的數(shù)據(jù),?如程序運?需要從中讀取數(shù)據(jù)的?件,或者輸出內(nèi)容的?件。

本篇討論的是數(shù)據(jù)?件。

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

其實有時候我們會把信息輸出到磁盤上,當(dāng)需要的時候再從磁盤上把數(shù)據(jù)讀取到內(nèi)存中使?,這?處理的就是磁盤上?件。

文件名

?個?件要有?個唯?的?件標識,以便??識別和引?。 ?件名包含3部分:?件路徑+?件主?名+?件后綴 例如: c:\code\test.txt 為了?便起?,?件標識常被稱為?件名。

二進制文件和文本文件

根據(jù)數(shù)據(jù)的組織形式,數(shù)據(jù)?件被稱為?本?件或者?進制?件。 數(shù)據(jù)在內(nèi)存中以?進制的形式存儲,如果不加轉(zhuǎn)換的輸出到外存,就是?進制?件。 如果要求在外存上以ASCII碼的形式存儲,則需要在存儲前轉(zhuǎn)換。以ASCII字符的形式存儲的?件就是?本?件。

?個數(shù)據(jù)在內(nèi)存中是怎么存儲的呢 字符?律以ASCII形式存儲,數(shù)值型數(shù)據(jù)既可以?ASCII形式存儲,也可以使??進制形式存儲。 如有整數(shù)10000,如果以ASCII碼的形式輸出到磁盤,則磁盤中占?5個字節(jié)(每個字符?個字節(jié)),??進制形式輸出,則在磁盤上只占4個字節(jié)(VS2019測試)。

?進制形式輸出不一定占用字節(jié)小,比如給一個整數(shù)1,ASCII碼形式輸出占?1個字節(jié),二進制的占?4個字節(jié)

文本文件我們是可以看到的

二進制

下面這個fwite(a的地址,多少字節(jié),寫多少次,寫到關(guān)聯(lián)的p)

int main()

{

int a = 10000;

FILE* p = fopen("test.txt", "wb");//打開文件

fwrite(&a, 4, 1, p);//寫入二進制

fclose(p);//關(guān)閉文件

p = NULL;

return 0;

}

輸出的東西我們都看不懂,因為存放的是二進制

我們可以用vs的二進制編輯器打開查看

這個是小端存放的,所以是倒過來的

文件的打開和關(guān)閉

流和標準流、

我們程序的數(shù)據(jù)需要輸出到各種外部設(shè)備,也需要從外部設(shè)備獲取數(shù)據(jù),不同的外部設(shè)備的輸?輸出操作各不相同,為了?便程序員對各種設(shè)備進??便的操作,我們抽象出了流的概念,我們可以把流想象成流淌著字符的河。C程序針對?件、畫?、鍵盤等的數(shù)據(jù)輸?輸出操作都是通過流操作的。 ?般情況下,我們要想向流?寫數(shù)據(jù),或者從流中讀取數(shù)據(jù),都是要打開流,然后操作。

標準流

為什么我們從鍵盤上輸入數(shù)據(jù),向屏幕輸出數(shù)據(jù),并沒有打開流呢?

那是因為C語?程序在啟動的時候,默認打開了3個流:

stdin --?標準輸?流,在?多數(shù)的環(huán)境中從鍵盤輸?,scanf函數(shù)就是從標準輸?流中讀取數(shù)據(jù)。stdout -- 標準輸出流,?多數(shù)的環(huán)境中輸出?顯?器界?,printf函數(shù)就是將信息輸出到標準輸出流中。stderr -- 標準錯誤流,?多數(shù)環(huán)境中輸出到顯?器界?。

這是默認打開了這三個流,我們使?scanf、printf等函數(shù)就可以直接進?輸?輸出操作的。stdin、stdout、stderr三個流的類型是: FILE* ,通常稱為?件指針。 C語?中,就是通過 FILE* 的?件指針來維護流的各種操作的。

文件指針

緩沖?件系統(tǒng)中,關(guān)鍵的概念是“?件類型指針”,簡稱“?件指針”。

每個被使?的?件都在內(nèi)存中開辟了?個相應(yīng)的?件信息區(qū),?來存放?件的相關(guān)信息(如?件的名字,?件狀態(tài)及?件當(dāng)前的位置等)。這些信息是保存在?個結(jié)構(gòu)體變量中的。該結(jié)構(gòu)體類型是由系統(tǒng)聲明的,取名FILE.

例如,VS2013編譯環(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;

不同的C編譯器的FILE類型包含的內(nèi)容不完全相同,但是?同?異。 每當(dāng)打開?個?件的時候,系統(tǒng)會根據(jù)?件的情況?動創(chuàng)建?個FILE結(jié)構(gòu)的變量,并填充其中的信 息,使?者不必關(guān)?細節(jié)。 ?般都是通過?個FILE的指針來維護這個FILE結(jié)構(gòu)的變量,這樣使?起來更加?便。

下?我們可以創(chuàng)建?個FILE*的指針變量:

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

定義pf是?個指向FILE類型數(shù)據(jù)的指針變量??梢允筽f指向某個?件的?件信息區(qū)(是?個結(jié)構(gòu)體變量)。通過該?件信息區(qū)中的信息就能夠訪問該?件。也就是說,通過?件指針變量能夠間接找到與它關(guān)聯(lián)的?件。

比如:

文件的打開和關(guān)閉

打開文件就是打開流

讀寫文件就是讀寫流

關(guān)閉文件就是關(guān)閉流

我們只需要關(guān)注文件操作進行,流的操作是底層的操作我們不用關(guān)心

?件在讀寫之前應(yīng)該先打開?件,在使?結(jié)束之后應(yīng)該關(guān)閉?件。

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

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

int main()

{

//打開文件

//打開文件成功,返回有效指針

//打開失敗,返回NULL

//當(dāng)然也可以用路徑打開文件

FILE* p = fopen("data.txt", "w");

//判斷是不是NULL

if (p == NULL)

{

//是就報錯

perror("fopen");

return 1;

}

//關(guān)閉文件

fclose(p);

//給p賦值NULL

p = NULL;

return 0;

}

文件打開方式

?件使??式含義如果指定?件不存在“r”(只讀)為了輸?數(shù)據(jù),打開?個已經(jīng)存在的?本?件出錯“w”(只寫)為了輸出數(shù)據(jù),打開?個?本?件建??個新的?件“a”(追加)向?本?件尾添加數(shù)據(jù)建??個新的?件“rb”(只讀)為了輸?數(shù)據(jù),打開?個?進制?件出錯“wb”(只寫)為了輸出數(shù)據(jù),打開?個?進制?件?建??個新的?件“ab”(追加)向?個?進制?件尾添加數(shù)據(jù)?建??個新的?件“r+”(讀寫)為了讀和寫,打開?個?本?件出錯“w+”(讀寫)為了讀和寫,建議?個新的?件建??個新的?件“a+”(讀寫)打開?個?件,在?件尾進?讀寫建??個新的?件“rb+”(讀寫)為了讀和寫打開?個?進制?件出錯“wb+”(讀寫)為了讀和寫,新建?個新的?進制?件建??個新的?件“ab+”(讀寫)打開?個?進制?件,在?件尾進?讀和寫建??個新的?件

文件的順序讀寫

順序讀寫函數(shù)介紹:

前6個函數(shù)是讀和寫的都是文本信息,后面2個是二進制信息

函數(shù)名功能適用于fgetc字符輸?函數(shù)(讀字符)所有輸?流fputc字符輸出函數(shù)(寫字符)所有輸出流fgets?本?輸?函數(shù)(讀字符串)所有輸?流fputs?本?輸出函數(shù)(寫字符串)所有輸出流fscanf格式化輸?函數(shù)(可以讀所有類型)所有輸?流fprintf格式化輸出函數(shù)所有輸出流fread二進制輸入文件fwrite二進制輸出文件

l

fputc函數(shù)示范(寫字符)

fputc是寫字符的,這個函數(shù)一次只能輸出一個字符

int main()

{

//打開文件

FILE* p = fopen("data.txt", "w");

if (p == NULL)

{

perror("fopen");

return 1;

}

//寫入文件

fputc('a', p);

fputc('b', p);

fputc('c', p);

fputc('d', p);

fputc('e', p);

fputc('f', p);

//關(guān)閉文件

fclose(p);

p = NULL;

return 0;

}

fputc可以循環(huán)寫入

int main()

{

//打開文件

FILE* p = fopen("data.txt", "w");

if (p == NULL)

{

perror("fopen");

return 1;

}

//寫入文件

for (int i = 'a'; i <= 'z'; i++)

{

fputc(i, p);

}

//關(guān)閉文件

fclose(p);

p = NULL;

return 0;

}

fgetc函數(shù)示范(讀字符)

讀取正常的時候,返回讀取到的字符的ASCII碼值

讀取失敗的時候,返回EOF

EOF是一個文件的結(jié)束標志

下面這個代碼我們可以看到從文件里讀取了5個字符。

int main()

{

//打開文件

FILE* p = fopen("data.txt", "r");

if (p == NULL)

{

perror("fopen");

return 1;

}

//讀文件

int r = fgetc(p);

printf("%c\n", r);

r = fgetc(p);

printf("%c\n", r);

r = fgetc(p);

printf("%c\n", r);

r = fgetc(p);

printf("%c\n", r);

r = fgetc(p);

printf("%c\n", r);

//關(guān)閉文件

fclose(p);

p = NULL;

}

我們也可以用循環(huán)的方式進行讀

int main()

{

//打開文件

FILE* p = fopen("data.txt", "r");

if (p == NULL)

{

perror("fopen");

return 1;

}

//讀文件

int r = 0;

while ((r = fgetc(p)) != EOF)

{

printf("%c\n", r);

}

//關(guān)閉文件

fclose(p);

p = NULL;

}

(字符)stdin標準輸入流和stdout標準輸出流

stdin --?標準輸?流,在?多數(shù)的環(huán)境中從鍵盤輸?,scanf函數(shù)就是從標準輸?流中讀取數(shù)據(jù)。stdout -- 標準輸出流,?多數(shù)的環(huán)境中輸出?顯?器界?,printf函數(shù)就是將信息輸出到標準輸出流中。

int main()

{

int r = fgetc(stdin);//標準輸入流(從鍵盤讀)

fputc(r, stdout);//標準輸出流(寫到屏幕上)

return 0;

}

fputs函數(shù)的示范(寫字符串)

這個函數(shù)可以往文件里寫字符串

int main()

{

//打開文件

FILE* p = fopen("data.txt", "w");

if (p == NULL)

{

perror("fopen");

return 1;

}

//寫入文件

fputs("您好小明,今天有空嗎", p );

//關(guān)閉文件

fclose(p);

p = NULL;

}

fgets函數(shù)示范(讀字符串)

這個函數(shù)是從文件里,讀取字符串出來

下面這代碼,我們要讀取3個字符,我們可以看到實際上只讀取了2個字符,編譯器會在后面加個\0

下面這個代碼,沒有讀取到w,這是為什么呢,因為這個函數(shù)是文本行的讀取,所以讀取到\n會停下來,然后呢編譯器在后面加\0

(字符串)stdin標準輸入流和stdout標準輸出流

int main()

{

char arr[20] = { 0 };

//從鍵盤讀數(shù)據(jù)

fgets(arr, 10, stdin);

//寫到屏幕上

fputs(arr, stdout);

}

fprintf(寫整數(shù),浮點數(shù),字符,字符串)

fprintf和printf的寫法是一樣的只不過fprintf是將數(shù)值寫到文件里,所以第一個參數(shù)是流。

只要是printf能打印的,fprintf都能寫到文件里

int main()

{

char a[20] = "小明";

int b = 18;

float c = 75.5f;

//打開文件

FILE* p = fopen("data.txt", "w");

if (p == NULL)

{

perror("fopen");

return 1;

}

//寫入文件

fprintf(p ,"%s %d %f", a, b, c);

//關(guān)閉文件

fclose(p);

p = NULL;

}

下面這代碼我們也可以用結(jié)構(gòu)體的方式

fscanf(讀整數(shù),浮點數(shù),字符,字符串)

fscanf和scanf也是差不多一樣的,scanf是讀取鍵盤,fscanf是讀取文件數(shù)據(jù)

下面這個代碼是讀取文件的數(shù)據(jù)放到結(jié)構(gòu)體變量里,然后進行打印結(jié)構(gòu)體

struct a

{

char a[20];

int b;

float c;

};

int main()

{

struct a arr = { 0 };

//打開文件

FILE* p = fopen("data.txt", "r");

if (p == NULL)

{

perror("fopen");

return 1;

}

//讀文件

fscanf(p , "%s %d %f", &arr.a, &arr.b, &arr.c);

//打印到屏幕上

printf("%s %d %.2f", arr.a, arr.b, arr.c);

//關(guān)閉文件

fclose(p);

p = NULL;

}

(整數(shù),浮點數(shù),字符,字符串)stdin標準輸入流和stdout標準輸出流

struct a

{

char a[20];

int b;

float c;

};

int main()

{

struct a arr = { 0 };

//讀取鍵盤

fscanf(stdin, "%s %d %f", &arr.a, &arr.b, &arr.c);

//打印到屏幕上

fprintf(stdout,"%s %d %.2f", arr.a, arr.b, arr.c);

}

對比一組函數(shù):

scanf / fscanf /?sscanf printf / fprintf / sprintf

scanf和printf? ?針對標準輸入流/標準輸出流的 格式化 輸入/輸出函數(shù)

fscanf和fprintf??針對所有輸入流/所有輸出流的 格式化 輸入/輸出函數(shù)

sprintf:將格式化的數(shù)據(jù)轉(zhuǎn)換成字符串。

sscanf:從字符串中提取格式化的數(shù)據(jù)。

sprintf:其實是將格式化的數(shù)據(jù)寫到字符串中(可以理解為將格式化的數(shù)據(jù)轉(zhuǎn)換成字符串)

如果有很多數(shù)據(jù)需要整合成字符串就可以使用sprintf

struct a

{

char a[20];

int b;

float c;

};

int main()

{

char arr[99] = { 0 };

struct a p = { "小虎",33,65.9};

//將p里的數(shù)據(jù)轉(zhuǎn)換成字符串,放到arr數(shù)組中

sprintf(arr,"%s %d %.2f", p.a, p.b, p.c);

printf("%s", arr);

return 0;

}

sscanf:是從字符串中提取格式化的數(shù)據(jù),可以理解為將字符串轉(zhuǎn)換成格式化的數(shù)據(jù)

struct a

{

char a[20];

int b;

float c;

};

int main()

{

char arr[99] = { 0 };

struct a p = { "小虎",33,65.9 };

//將p里的數(shù)據(jù)轉(zhuǎn)換成字符串,放到arr數(shù)組中

sprintf(arr, "%s %d %.2f", p.a, p.b, p.c);

struct a kk = { 0 };

//從字符串里讀取格式化的數(shù)據(jù),轉(zhuǎn)換后,放到kk中

sscanf(arr,"%s %d %f", kk.a, &kk.b, &kk.c);

//打印

printf("%s %d %.2f", kk.a, kk.b, kk.c);

return 0;

}

fwrite函數(shù)

這個函數(shù)是以二進制形式寫到文件里,

fwrite第一個參數(shù)是數(shù)據(jù),第二個參數(shù)是類型的大小,第三個參數(shù)是要寫多少,第四個參數(shù)是流(把數(shù)據(jù)寫到文件里)。

下面這代碼我們可以看到以二進制文件寫到文件里,二進制我們當(dāng)然是看不懂的。

struct a

{

char a[20];

int b;

float c;

};

int main()

{

struct a ps = { "asdfyg",25,88.8f };

//打開文件

FILE* p = fopen("data.txt", "wb");

if (p == NULL)

{

perror("fopen");

return 1;

}

//寫入二進制到文件

fwrite(&ps, sizeof(struct a), 1, p);

//關(guān)閉文件

fclose(p);

p = NULL;

return 0;

}

fread函數(shù)

這個函數(shù)是讀取二進制信息

fwrite第一個參數(shù)是讀到的數(shù)據(jù)放的位置,第二個參數(shù)是類型的大小,第三個參數(shù)是要讀多少,第四個參數(shù)是流(從流讀取數(shù)據(jù))。

下面這代碼我們可以看到,從二進制讀取信息,打印在屏幕上

struct a

{

char a[20];

int b;

float c;

};

int main()

{

struct a ps = { 0 };

//打開文件

FILE* p = fopen("data.txt", "rb");

if (p == NULL)

{

perror("fopen");

return 1;

}

//讀取二進制文件

fread(&ps,sizeof(struct a), 1 , p );

//打印

printf("%s %d %f", ps.a, ps.b, ps.c);

//關(guān)閉文件

fclose(p);

p = NULL;

}

文件的隨機讀寫

順序讀寫是一行一行的讀寫,隨機讀寫是想讀寫那個就讀寫那個

fseek

fseek根據(jù)?件指針的位置和偏移量來定位?件指針(文件內(nèi)容的光標)。

第一個參數(shù)是流,第二個參數(shù)是偏移量,

第三個參數(shù)定位文件指針:

SEEK_SET(是文件開頭的位置)

SEEK_CUR(文件指針的當(dāng)前位置(光標))

SEEK_END(文件末尾)

作用是:

用SEEK_SET從文件開頭的位置偏移到后面

用SEEK_CUR從光標的位置向后面偏移

用SEEK_END文件末尾向前面偏移

向前面偏移用正數(shù),向后偏移用負數(shù)

從文件開頭向后偏移

讀取a和b后,定位文件指針,SEEK_SET從文件開頭向后偏移了6,讀取了后面的3個hhh

從光標位置偏移

當(dāng)我們讀取了a和b光標會在b的后面,定位文件指針,SEEK_CUR從光標的位置向后面偏移4個,讀取了后面的3個hhh。

文件末尾向前面偏移

SEEK_END從文件末尾向前面偏移了-6,讀取了后面的3個d e f

ftell函數(shù)

ftell返回?件指針相對于起始位置的偏移量。

ftell計算從起始位置到光標的偏移量。

int main()

{

//打開文件

FILE* p = fopen("data.txt", "r");

if (p == NULL)

{

perror("fopen");

return 1;

}

//讀文件

int r = 0;

//定位文件指針

fseek(p, -6, SEEK_END);

r = fgetc(p);//d

printf("%c\n", r);

r = fgetc(p);//e

printf("%c\n", r);

r = fgetc(p);//f

printf("%c\n", r);

printf("%d\n", ftell(p));

//關(guān)閉文件

fclose(p);

p = NULL;

}

?rewind函數(shù)

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

就是讓光標來到起始位置

int main()

{

//打開文件

FILE* p = fopen("data.txt", "r");

if (p == NULL)

{

perror("fopen");

return 1;

}

//讀文件

int r = 0;

r = fgetc(p);//a

printf("%c\n", r);

r = fgetc(p);//b

printf("%c\n", r);

r = fgetc(p);//c

printf("%c\n", r);

//將文件指針重新定位到文件的起始位置

rewind(p);

r = fgetc(p);//a

printf("%c\n", r);

r = fgetc(p);//b

printf("%c\n", r);

r = fgetc(p);//c

printf("%c\n", r);

//關(guān)閉文件

fclose(p);

p = NULL;

}

?件讀取結(jié)束的判定

被錯誤使?的 feof?

牢記:在?件讀取過程中,不能?feof函數(shù)的返回值直接來判斷?件的是否結(jié)束。 feof 的作?是:當(dāng)?件讀取結(jié)束的時候,判斷是讀取結(jié)束的原因是否是:遇到?件尾結(jié)束。

?本?件讀取是否結(jié)束,判斷返回值是否為 EOF ( fgetc ),或者 NULL ( fgets ) 例如:

fgetc 判斷是否為 EOF . fgets 判斷返回值是否為 NULL .

?進制?件的讀取結(jié)束判斷,判斷返回值是否?于實際要讀的個數(shù)。 例如:

?fread判斷返回值是否?于實際要讀的個數(shù)。

EOF也可以拿來文件的結(jié)束標志

feof函數(shù)不是用來判斷文件是否結(jié)束的?。?!

1

在讀取文件的過程中,有可能讀取文件結(jié)束

結(jié)束的原因:

1.遇到文件末尾

2.遇到錯誤了

?本?件的例?:

feof是在已經(jīng)結(jié)束了,判斷結(jié)束的原因是什么。

#include

#include

int main(void)

{

int c; // 注意:int,?char,要求處理EOF

FILE* fp = fopen("test.txt", "r");

if (!fp) {

perror("File opening failed");

return EXIT_FAILURE;

}

//fgetc 當(dāng)讀取失敗的時候或者遇到?件結(jié)束的時候,都會返回EOF

while ((c = fgetc(fp)) != EOF) // 標準C I/O讀取?件循環(huán)

{

putchar(c);

}

//判斷是什么原因結(jié)束的

if (ferror(fp))

//遇到錯誤了

puts("I/O error when reading");

else if (feof(fp))

//遇到文件末尾

puts("End of file reached successfully");

fclose(fp);

}

?進制?件的例?:

#include

enum { SIZE = 5 };

int main(void)

{

double a[SIZE] = { 1.,2.,3.,4.,5. };

FILE* fp = fopen("test.bin", "wb");

fwrite(a, sizeof * a, SIZE, fp); // 寫 double 的數(shù)組

fclose(fp);

double b[SIZE];

fp = fopen("test.bin", "rb");

size_t ret_code = fread(b, sizeof * b, SIZE, fp); // 讀 double 的數(shù)組

if (ret_code == SIZE) {

puts("Array read successfully, contents: ");

for (int n = 0; n < SIZE; ++n)

printf("%f ", b[n]);

putchar('\n');

}

else { // error handling

if (feof(fp))

printf("Error reading test.bin: unexpected end of file\n");

else if (ferror(fp)) {

perror("Error reading test.bin");

}

}

fclose(fp);

}

下面這代碼我們可以看到只讀取了一個字符,沒有遇到文件末尾,feof返回0

當(dāng)我們讀取完到遇到文件末尾返回1

拷貝字符串代碼

#include

#include

int main()

{

//打開文件

FILE* p1 = fopen("data1.txt", "r");

if (p1 == NULL)

{

perror("fopen");

return 1;

}

FILE* p2 = fopen("data2.txt", "w");

if (p2 == NULL)

{

perror("fopen");

fclose(p1);

p1 = NULL;

return 1;

}

//復(fù)制

int r = 0;

while ((r = fgetc(p1)) != EOF)

{

fputc(r, p2);

}

fclose(p1);

p1 == NULL;

fclose(p2);

p2 = NULL;

return 0;

}

文件緩沖區(qū)

ANSIC 標準采?“緩沖?件系統(tǒng)”處理的數(shù)據(jù)?件的,所謂緩沖?件系統(tǒng)是指系統(tǒng)?動地在內(nèi)存中為程序中每?個正在使?的?件開辟?塊“?件緩沖區(qū)”。從內(nèi)存向磁盤輸出數(shù)據(jù)會先送到內(nèi)存中的緩沖區(qū),裝滿緩沖區(qū)后才?起送到磁盤上。如果從磁盤向計算機讀?數(shù)據(jù),則從磁盤?件中讀取數(shù)據(jù)輸?到內(nèi)存緩沖區(qū)(充滿緩沖區(qū)),然后再從緩沖區(qū)逐個地將數(shù)據(jù)送到程序數(shù)據(jù)區(qū)(程序變量等)。緩沖區(qū)的??根據(jù)C編譯系統(tǒng)決定的。

系統(tǒng)會在內(nèi)存中開辟一塊文件緩沖區(qū),當(dāng)我們把數(shù)據(jù)寫到文件里(也就是硬盤),會先把數(shù)據(jù)放到輸出緩沖區(qū),放滿了輸出緩沖區(qū),才?起送到硬盤上。

輸入緩沖區(qū)元素一樣,讀的數(shù)據(jù),放滿了輸入緩沖區(qū),然后再從緩沖區(qū)逐個地將數(shù)據(jù)送到程序數(shù)據(jù)區(qū)(程序變量等)。

下面這有個代碼

#include

#include

//VS2019 WIN11環(huán)境測試

int main()

{

FILE*pf = fopen("test.txt", "w");

fputs("abcdef", pf); //先將代碼放在輸出緩沖區(qū)

printf("睡眠10秒-已經(jīng)寫數(shù)據(jù)了,打開test.txt?件,發(fā)現(xiàn)?件沒有內(nèi)容\n");

Sleep(10000);

printf("刷新緩沖區(qū)\n");

fflush(pf); //刷新緩沖區(qū)時,才將輸出緩沖區(qū)的數(shù)據(jù)寫到?件(磁盤)

//注:fflush 在?版本的VS上不能使?了

printf("再睡眠10秒-此時,再次打開test.txt?件,?件有內(nèi)容了\n");

Sleep(10000);

fclose(pf);

//注:fclose在關(guān)閉?件的時候,也會刷新緩沖區(qū)

pf = NULL;

return 0;

}

下面這代碼我們可以看到,把字符串放到了輸出緩沖區(qū),但是還沒有刷新緩沖區(qū)(也就是還沒有放到硬盤)

下面代碼,已經(jīng)刷新緩沖區(qū)了(也就是放到硬盤了),我們可以看到,字符串已經(jīng)放到文件(硬盤)里了

這?可以得出?個結(jié)論:因為有緩沖區(qū)的存在,C語?在操作?件的時候,需要做刷新緩沖區(qū)或者在?件操作結(jié)束的時候關(guān)閉?件。如果不做,可能導(dǎo)致讀寫?件的問題。

柚子快報邀請碼778899分享:開發(fā)語言 C語言:文件操作

http://yzkb.51969.com/

推薦鏈接

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19027191.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機訪問

文章目錄