- 本篇會加入個人的所謂‘魚式瘋言’
- ??????魚式瘋言:??????此瘋言非彼瘋言,而是理解過并總結出來通俗易懂的大白話,我會盡可能的在每個概念后插入魚式瘋言,幫助大家理解的,可能說的不是那么嚴謹.但小編初心是能讓更多人能接受我們這個概念
前言
💕💕💕艾迪巴帝,友子們,今天我們將推開 文件操作 的大門
主要講的有:
- ?件的引入?
- ?進制?件和?本?件?
- ?件的打開和關閉
- ?件的順序讀寫
💖💖💖
一.文件的引入
1.為什么要使用文件?
如果沒有?件,我們寫的程序的數據是存儲在電腦的內存中
如果程序退出,內存回收,數據就丟失了,等再次運?程序,是看不到上次程序的數據的
如果要將數據進?持久化的保存,我們可以使? ?件。
2. 什么是文件
磁盤上的?件是?件。
但是在程序設計中,我們?般談的?件有兩種:程序?件、數據?件(從?件功能的?度來分類的)
2.1 程序文件
程序?件包括源程序?件(后綴為 .c )
?標?件(windows環境后綴為 .obj)
可執?程序(windows環境后綴為 .exe)。
2.2 數據?件
?件的內容不?定是程序,?是程序運?時讀寫的數據,
?如程序運?需要從中讀取數據的?件,或 者輸出內容的?件。
本章討論的是數據?件。
在以前各章所處理數據的輸?輸出都是以終端為對象的,即從終端的鍵盤輸?數據,運?結果顯?到 顯?器上。
其實有時候我們會把信息輸出到磁盤上,當需要的時候再從磁盤上把數據讀取到內存中使?,這?處理的就是磁盤上?件.
2.3 文件名
?個?件要有?個唯?的?件標識,以便??識別和引?。
?件名包含3部分:?件路徑+?件名主?+?件后綴
例如: c:\code\test.txt
為了?便起?,?件標識 常被稱為 ?件名
魚式瘋言
就是說呢😊😊😊
我們文件時在磁盤上的,用來存儲數據的,文件可以放程序也可以放數據,我們可以在終端(下面第一張的小黑框框),也可以在我們下面磁盤上處理(下面第二張文件路徑圖)
(1).
(2).
3.二進制文件和文本文件
根據數據的組織形式,數據?件被稱為?本?件 或者?進制?件。
數據在內存中以?進制的形式存儲,如果不加轉換的輸出到外存,就是?進制?件。
如果要求在外存上以ASCII碼的形式存儲,則需要在存儲前轉換。以ASCII字符的形式存儲的?件就是?本?件。
?個數據在內存中是怎么存儲的呢?
字符?律以ASCII形式存儲,數值型數據既可以?ASCII形式存儲,也可以使??進制形式存儲。
如有整數10000,如果以ASCII碼的形式輸出到磁盤,則磁盤中占?5個字節(每個字符?個字節),??進制形式輸出,則在磁盤上只占4個字節
#include <stdio.h>
int main()
{int a = 10000;FILE * pf = fopen("test.txt", "wb");fwrite(&a, 4, 1, pf);//?進制的形式寫到?件中 fclose(pf);pf = NULL; return 0;
}
文本文件是不打開的哦??????
那該怎么辦呢?
請寶子們看下面分解
4.文件打開和關閉
4.1流和標準流
<1> 流
我們程序的數據需要輸出到各種外部設備
也需要從外部設備獲取數據
不同的外部設備的輸?輸出 操作各不相同
為了?便程序員對各種設備進??便的操作,我們抽象出了 流 的概念,我們可以把流 想象成流淌著字符的河。
C程序針對?件、畫?、鍵盤等的數據輸?輸出操作都是通過流操作的。
?般情況下,我們要想向流?寫數據,或者從流中讀取數據,都是要打開 流,然后操作。
<2> 標準流
那為什么我們從鍵盤輸?數據,向屏幕上輸出數據,并沒有打開流呢? 那是因為C語?程序在啟動的時候,默認打開了3個流:
? stdin - 標準輸?流,在?多數的環境中從鍵盤輸?,scanf函數就是從標準輸?流中讀取數據。
? stdout - 標準輸出流,?多數的環境中輸出?顯?器界?,printf函數就是將信息輸出到標準輸出 流中。
? stderr - 標準錯誤流,?多數環境中輸出到顯?器界?。
<3> 標準流的栗子🌰
#include<stdio.h>
int main()
{char arr[10]="abcdefg\n";fprintf(stdout,arr);//用 fprintf 標準輸出流輸出printf(arr);//普通的 printf 輸出
}
魚式瘋言
其實,在我們的運行程序時
我們的編譯器就會在底層運行用到我們這三個標準流
輸入,輸出,錯誤。
小伙伴了解一下即可,不需要深入研究
這是默認打開了這三個流,我們使?scanf、printf等函數就可以直接進?輸?輸出操作的。
stdin、stdout、stderr 三個流的類型是:
FILE* ,通常稱為?件指針。
C語?中,就是通過 FILE* 的?件指針來維護流的各種操作的。
魚式瘋言
啥是 流 呢?
說白了,就是一個中介,一個中轉站,一個快遞員,一個轉換器,一個中樞樞紐…
上面我們提及了一個陌生的概念,文件指針
這是什么呢?
不妨小伙伴都和我一起繼續往下找找答案吧😊😊😊
4.2 文件指針
緩沖?件系統中,關鍵的概念是“?件類型指針”,簡稱“?件指針”。 每個被使?的?件都在內存中開辟了?個相應的?件信息區,?來存放?件的相關信息(如?件的名 字,?件狀態及?件當前的位置等)。
這些信息是保存在?個結構體變量中的。該結構體類型是由系 統聲明的,取名FILE
例如,VS2013編譯環境提供的 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類型包含的內容不完全相同,但是?同?異。 每當打開?個?件的時候,系統會根據?件的情況?動創建?個FILE結構的變量,并填充其中的信 息,使?者不必關?細節。 ?般都是通過?個FILE的指針來維護這個FILE結構的變量,這樣使?起來更加?便。 下?我們可以創建?個FILE*的指針變量:
FILE* pf;
//?件指針變量
這上面的概念友友們小小過過眼,知道這個概念就歐克啦
咱們主要的是知道并掌握文件指針的使用 ! ! !
定義pf是?個指向FILE類型數據的指針變量。
可以使pf指向某個?件的?件信息區(是?個結構體變 量)。
通過該?件信息區中的信息就能夠訪問該?件。
魚式瘋言
通過?件指針變量能夠間接找到與它關聯的?件.
接下來,該我們實操起來啦💕💕💕
4.3 文件的打開和關閉
?件在讀寫之前應該先打開?件,在使?結束之后應該關閉?件。
在編寫程序的時候,在打開?件的同時,都會返回?個 FILE* 的指針變量指向該?件,也相當于建?了 指針和?件的關系。
ANSIC 規定使? fopen 函數來打開?件, fclose 來關閉?件。
//打開?件
FILE * fopen ( const char * filename, const char * mode );
//關閉?件
int fclose ( FILE * stream );
mode 表??件的打開模式,下?都是?件的打開模式:
友子們是不是都不想看了,我也是😭😭😭
太多了吧,不過我們只需要會前面的 **“r”**和 **“w”**就足夠啦!
4.3.1 “w” 的栗子說明
/* fopen fclose example */
#include <stdio.h>
int main()
{FILE* pFile;//打開?件pFile = fopen("myfile.txt", "w");//?件操作if (pFile != NULL){fputs("fopen example", pFile);//關閉?件fclose(pFile);}return 0;
}
魚式瘋言:
有該文件我們可以用 “w” 自行打開,
如果沒有該文件的話,我們就可以通過 “w” 自動創建
具體對文件的流程就是
打開文件——>文件操作——>關閉文件.
4.3.2 “r” 的栗子說明
就像上面這樣要是沒有該文件的情況,
如果我們用 “r” 來實踐呢!!!
/* fopen fclose example */
#include <stdio.h>
int main()
{FILE* pFile;//打開?件pFile = fopen("myfile.txt", "r");//?件操作if (pFile == NULL){perror("fopen");return 1;}//關閉?件fclose(pFile);return 0;
}
小伙伴都看清楚區別了吧 “w” 和 “r”的區別吧😁😁😁
魚式瘋言
我是這樣理解的
w—> write 是寫的意思吧,如果我們要寫,當我們該文件名時,是不是可以先創個文件再寫呢 ! ! !
r——> read 是讀的意思呢,如果我們要讀,那如果也沒有該文件名呢,連個文件都沒有肯定會報錯呢! ! !
如果都有該文件名,這樣我們就可以用下面的順序讀寫函數對文件進行操作了。💖💖💖
5.文件的順序讀寫
5.1 順序讀寫函數介紹
蛙趣,好多啊😣😣😣
沒關系,下面由小編來帶著大家一起學
咱們兩兩搭配起來用哦💖💖💖
5.2 fgetc 與 fputc
/*fputc與fgetc_test*/#include<stdio.h>
int main()
{FILE* putpile = fopen("gt.txt", "w");if (putpile == NULL){perror("fopen->putpile");return 1;} for (int i = 0; i < 26; i++){fputc('a' + i, putpile);}fclose(putpile);putpile = NULL;//這里一定要要指針置為空//否則就有可能出差錯FILE* getpile = fopen("gt.txt", "r");if (getpile == NULL){perror("fopen->getpile");return 1;}int ch = fgetc(getpile);printf("%c\n", ch);ch = fgetc(getpile);printf("%c\n", ch);ch = fgetc(getpile);printf("%c\n", ch);ch = fgetc(getpile);printf("%c\n", ch);//for (int i = 0; i < 4; i++)//{// printf("%c\n", fgetc(getpile));//}//也可用循環打印fclose(getpile);getpile = NULL;//最后要關閉文件指針哦return 0;
}
根據上面的代碼,我們就可以對文本進行 寫 與 讀 啦 !!!
5.3 fgets 與 fputs
<1>.舉個栗子
#include<stdio.h>
int main()
{FILE* putpile = fopen("gt.txt", "w");if (putpile==NULL){perror("fopen");return 1;}fputs("abcde", putpile);fclose(putpile);putpile = NULL;FILE* getpile = fopen("gt.txt", "r");if (getpile==NULL){perror(fopen);return 1;}char arr[5];fgets(arr,4, getpile); printf(arr);fclose(getpile);getpile = NULL;return 0;
}
魚式瘋言
唯一要注意一點是:
num : 這里是要指定輸出字符串大小的
5.3. fprintf 與 fscanf
<1>.舉個栗子
struct Stu
{char name[20];int age;float score;
};
#include<stdio.h>
//fprintf與fscanf_test
int main()
{struct Stu s1 = { "hehehhhh" ,112, 12.366 };struct Stu s2 = {0};FILE* pc = fopen("gt.txt", "w");if (pc==NULL){perror("fopen");return 1;}fprintf(pc, "%s %d %.1f", s1.name, s1.age, s1.score);//fprintf 可以用于寫文件fclose(pc);pc = NULL;FILE* pf = fopen("gt.txt", "r");if (pf == NULL){perror("fopen");return 1;}//寫讀文件//fscanf(pf, "%s %d %f", s1.name, &(s1.age), &(s1.score));//寫出該文件的內容拷貝在結構體 s 上fprintf(stdout, "%s %d %.1f\n", s1.name, s1.age, s1.score);//讀取或輸出該結構體printf("%s %d %.1f\n", s1.name, s1.age, s1.score);fclose(pf);pf = NULL;return 0;
}
w方式時,我們用 fprintf 可以寫入
r方式時,我們可以通過 fscanf 從文本中傳出數據到結構體
再通過標準輸出流 stdout 打印我們的或者 printf 直接輸出
5.4. fwrite 和 fread
<1>. fwrite 的栗子
//fwrite
#include<stdio.h>
struct Stu
{char name[20];int age;float score;
};
int main()
{struct Stu s = {"zhangsan", 20, 90.5};FILE* pf = fopen("data.txt", "wb");if (pf == NULL){return 1;}//二進制的形式寫文件fwrite(&s, sizeof(s), 1, pf);fclose(pf);pf = NULL;return 0;
}
前面我們看到fprintf寫進去的文本,
下面小伙伴來看看這兩者的區別
<2>. fread 的栗子
#include<stdio.h>
//fread_test
struct Stu
{char name[20];int age;float score;
};
int main()
{struct Stu s = { 0 };FILE* pf = fopen("data.txt", "rb");if (pf == NULL){return 1;}//二進制的形式讀文件fread(&s, sizeof(s), 1, pf);printf("%s %d %.1f\n", s.name, s.age, s.score);fclose(pf);pf = NULL;return 0;
}
上面我們講到了二進制文件在文本文件中是會變亂的
但我們的讀取還是一樣的讀取
魚式瘋言
這點充分說明了,文件的種類雖然不同,形式發生了改變 ,但是文件的內容一般不會改變.
以上順序讀寫函數的操作,啥叫 順序讀寫 呢🤔🤔🤔
顯而易見 順序 順序 就是當相當于我們C語言程序自上而下的順序執行一樣,后期我們會進一步講解我們的文件隨機讀寫,文件讀取的判定和文件緩沖區的講解…
友友們敬請期待哦 !!!
總結
🤞🤞🤞在本篇文章中,我們主要講解有
- ?件的引入的概念,類別!
- ?進制?件和?本?件的認識
- .文件指針的理解,以及利用函數對?件的打開和關閉
- ?件的順序讀寫,不同文件操作函數的理解以及實際操作文本文件和二進制文件。
💖💖💖本次博文就到這里了,感覺各位小伙伴的賞臉品讀小編寫的拙作哦,
如果覺得小編寫的還不錯的咱可支持三關下,不妥當的咱評論區指正
希望我的文章能給各位家人們帶來哪怕一點點的收獲就是小編創作的最大動力💖💖💖