柚子快報邀請碼778899分享:開發(fā)語言 C語言-文件操作
柚子快報邀請碼778899分享:開發(fā)語言 C語言-文件操作
文章目錄
?引言?文件操作1.為什么使用文件2.什么是文件2.1程序文件2.2數(shù)據(jù)文件2.3文件名
3.二進(jìn)制文件和文本文件3.1文本文件3.2二進(jìn)制文件
4.文件的打開和關(guān)閉4.1流和標(biāo)準(zhǔn)流4.2文件指針4.3文件的打開和關(guān)閉4.3.1打開文件4.3.2關(guān)閉文件
5.文件的順序讀寫5.1 讀取文件5.2寫入文件5.3fprintf printf sprintf fscanf scanf sscanf的使用5.3.1`fprintf`、`printf` 和 `sprintf` 函數(shù)5.3.2`fscanf`、`scanf` 和 `sscanf` 函數(shù)
6.文件的隨機(jī)讀寫6.1 `fseek` 函數(shù)**6.2`ftell` 函數(shù)**6.2 `rewind` 函數(shù)
7.文件讀取結(jié)束的判定7.1feof函數(shù)的使用
8.文件緩沖區(qū)
磊結(jié)語
?引言
在計算機(jī)編程領(lǐng)域,文件操作是一項(xiàng)基礎(chǔ)且關(guān)鍵的技能。無論是讀取配置文件、保存用戶數(shù)據(jù),還是處理日志信息,文件操作都扮演著重要角色。特別是在C語言中,文件操作的學(xué)習(xí)不僅幫助我們理解計算機(jī)如何管理數(shù)據(jù)存儲,還能夠深入理解內(nèi)存與磁盤之間的交互機(jī)制。本文將深入探討C語言中文件操作的各個方面,包括如何打開和關(guān)閉文件、讀取和寫入文件內(nèi)容,以及如何管理文件指針和處理文件緩沖區(qū)等內(nèi)容。
?文件操作
1.為什么使用文件
數(shù)據(jù)持久化:文件可以用來保存數(shù)據(jù),以便在程序結(jié)束后仍能訪問這些數(shù)據(jù)。這樣,即使計算機(jī)關(guān)機(jī)或程序崩潰,數(shù)據(jù)也不會丟失。
下面通過一段簡單示例來講解:
#include
int main()
{
int a=0;
scanf("%d",&a);
printf("%d",a);
return 0;
}
我們平時所寫的程序的數(shù)據(jù)都是存儲在電腦內(nèi)存中,如果我們將程序退出,內(nèi)存就會自動回收數(shù)據(jù)也就丟了,再次運(yùn)行程序就沒有上次程序的數(shù)據(jù).就像上面的代碼,我第一次運(yùn)行他,輸入a的值,下一次運(yùn)行a的值就不存在了.所以我們要通過文件的方式將數(shù)據(jù)保存下來.
數(shù)據(jù)共享:文件可以在不同的程序或設(shè)備之間傳輸和共享數(shù)據(jù)。例如,一個程序可以將數(shù)據(jù)寫入文件,另一個程序可以讀取這些文件來獲取數(shù)據(jù)。
存儲大數(shù)據(jù):文件可以存儲大量數(shù)據(jù),而這些數(shù)據(jù)可能不適合全部加載到內(nèi)存中。通過文件,程序可以處理超出內(nèi)存容量的大量數(shù)據(jù)。
備份和恢復(fù):文件可以用來備份重要數(shù)據(jù),防止數(shù)據(jù)丟失。例如,數(shù)據(jù)庫可以將數(shù)據(jù)定期導(dǎo)出到文件中,以便在數(shù)據(jù)損壞或丟失時進(jìn)行恢復(fù)。
2.什么是文件
文件是存儲在計算機(jī)存儲介質(zhì)(如硬盤、固態(tài)硬盤、光盤等)上的一組數(shù)據(jù),它具有特定的格式和結(jié)構(gòu),用于保存信息。
通常我們所接觸到的有兩種文件:程序文件,數(shù)據(jù)文件(從文件功能的角度分類).
2.1程序文件
程序文件是一種包含可執(zhí)行代碼或指令的文件,用于計算機(jī)執(zhí)行特定任務(wù)或程序。根據(jù)文件的用途和編程語言的不同,程序文件可以分為多種類型。如:源程序文件(.c),目標(biāo)文件(Windows下后綴為.obj),以及可執(zhí)行程序(Windows下后綴為.exe).
2.2數(shù)據(jù)文件
數(shù)據(jù)文件是用于存儲數(shù)據(jù)而非可執(zhí)行代碼的文件。它們在程序執(zhí)行過程中或之后被讀取和寫入,用于保存各種類型的信息。(下面我所講的內(nèi)容都是與數(shù)據(jù)文件有關(guān)的)
之前我們利用的scanf從鍵盤上接收數(shù)據(jù)到內(nèi)存中,是通過標(biāo)準(zhǔn)輸入流(后面會講解相關(guān)概念)進(jìn)行的,將數(shù)據(jù)打印到屏幕是通過標(biāo)準(zhǔn)輸出流進(jìn)行的.
圖示:
我們信息的輸出和輸入,不止通過鍵盤和鼠標(biāo),還可以通過磁盤進(jìn)行,會從磁盤上讀取信息,也會把信息輸出到磁盤上,下面會詳細(xì)講解.
2.3文件名
我們要找到一個文件,就必須找到該文件的唯一標(biāo)識,這個標(biāo)識就文件名.
文件名包括:文件路徑+文件名主干+文件名后綴
文件路徑:文件路徑是文件在文件系統(tǒng)中的位置。它可以是相對路徑(相對于當(dāng)前工作目錄)或絕對路徑(從根目錄開始的完整路徑)。
如:C:\Users\JohnDoe\Documents\example.txt那么C:\Users\JohnDoe\Documents\就是文件的路徑,example是文件名主干,文件后綴是.txt,所以C:\Users\JohnDoe\Documents\example.txt就是一個文件名.
3.二進(jìn)制文件和文本文件
二進(jìn)制文件和文本文件是兩種基本的文件類型,用于存儲不同類型的數(shù)據(jù)。理解它們的區(qū)別和用途對于數(shù)據(jù)處理和編程非常重要。
3.1文本文件
文本文件以可讀的文本形式存儲數(shù)據(jù),通常使用字符編碼(如ASCII或UTF-8)來表示字符。這些文件可以用任何文本編輯器打開和編輯。
特征
可讀性:文本文件包含人類可讀的字符,可以直接查看和編輯。編碼方式:使用字符編碼(如ASCII、UTF-8、UTF-16)來表示字符。擴(kuò)展名:常見的擴(kuò)展名包括 .txt、.csv、.html、.xml、.json 等。用途:用于存儲純文本數(shù)據(jù)、配置文件、源代碼、日志文件等。
3.2二進(jìn)制文件
二進(jìn)制文件以二進(jìn)制格式存儲數(shù)據(jù),即0和1的序列。這些文件通常包含特定格式的數(shù)據(jù),無法直接用文本編輯器查看和編輯,必須使用相應(yīng)的軟件進(jìn)行處理。
特征
不可讀性:二進(jìn)制文件包含計算機(jī)理解的二進(jìn)制數(shù)據(jù),通常對人類不可讀。數(shù)據(jù)存儲:以二進(jìn)制格式存儲數(shù)據(jù),緊湊且高效。擴(kuò)展名:常見的擴(kuò)展名包括 .bin、.exe、.jpg、.mp3、.dat 等。用途:用于存儲程序執(zhí)行文件、圖像、音頻、視頻、壓縮文件、數(shù)據(jù)庫文件等。
圖示講解:
在外存中以二進(jìn)制的形式存儲就是二進(jìn)制文件.在外存中以ASCII碼的形式存儲的文件就是文本文件
如果內(nèi)存有整數(shù)10000(十進(jìn)制),分別以兩種形式存儲到外存中會有什么區(qū)別呢?下面我將通過圖示帶你了解他們的區(qū)別
二進(jìn)制文件:
文本文件:
以文本文件存儲在硬盤中在磁盤上占用五個字節(jié),以二進(jìn)制文件存儲,在磁盤上占四個字節(jié).
4.文件的打開和關(guān)閉
4.1流和標(biāo)準(zhǔn)流
在C語言中,**流(stream)**是一個用于處理輸入輸出的抽象概念。流表示數(shù)據(jù)的有序序列,數(shù)據(jù)可以從流中讀出或?qū)懭肓髦小C總€打開的文件對應(yīng)一個流,標(biāo)準(zhǔn)庫函數(shù)通過流來處理文件操作。
流我們可以想象成河流,河流中有許多的魚,這些魚我們就可以把他比作是數(shù)據(jù),人會從河流中抓魚,和養(yǎng)魚,這個過程我們就可以看作程序中的相關(guān)操作.
一般情況下,我們想要向流里寫數(shù)據(jù),或者從流中讀取數(shù)據(jù),都是要打開流,然后進(jìn)行操作.類似的,我們要進(jìn)行抓魚養(yǎng)魚,也要走去河流旁邊.
標(biāo)準(zhǔn)流:
為什么我們從鍵盤輸入數(shù)據(jù),向屏幕上輸出數(shù)據(jù),沒有打開流呢?因?yàn)镃語言程序啟動時,就默認(rèn)打開了三個流,如下.
C語言提供了三種標(biāo)準(zhǔn)流(程序啟動時默認(rèn)打開):
標(biāo)準(zhǔn)輸入(stdin):通常連接到鍵盤,用于從標(biāo)準(zhǔn)輸入設(shè)備讀取數(shù)據(jù)。scanf函數(shù)就是從該流中讀取數(shù)據(jù)標(biāo)準(zhǔn)輸出(stdout):通常連接到顯示器,用于向標(biāo)準(zhǔn)輸出設(shè)備寫入數(shù)據(jù)。printf函數(shù)就是將信息輸出到該流中標(biāo)準(zhǔn)錯誤(stderr):通常連接到顯示器,用于向標(biāo)準(zhǔn)錯誤設(shè)備寫入錯誤信息。
stdin,stdout,stderr有共同的類型是:FILE* ,該類型稱為文件指針
C語言中就是通過,FILE*來維護(hù)流的各種操作
4.2文件指針
當(dāng)文件中信息想在程序當(dāng)中使用時,這個被使用的文件都會在內(nèi)存開辟一個文件信息區(qū),用來存放文件的相關(guān)信息.這些信息是保存在一個結(jié)構(gòu)體變量中的.該結(jié)構(gòu)體類型是由系統(tǒng)聲明的,取名為FILE.
在標(biāo)準(zhǔn)C庫中,F(xiàn)ILE 結(jié)構(gòu)體的定義通常是不公開的typedef struct _IO_FILE FILE;我們不要去關(guān)心該結(jié)構(gòu)體的具體內(nèi)容,我們只要知道,我們通過FILE* 來維護(hù)和操作FILE結(jié)構(gòu)的變量,實(shí)際上也就是在操作文件了.
4.3文件的打開和關(guān)閉
在C語言中,文件的打開和關(guān)閉是進(jìn)行文件操作的基本步驟,使用標(biāo)準(zhǔn)庫函數(shù)來完成。以下是關(guān)于文件的打開和關(guān)閉的詳細(xì)說明和示例:
4.3.1打開文件
在C語言中,可以使用 fopen 函數(shù)來打開文件。fopen 函數(shù)的原型如下:
FILE *fopen(const char *filename, const char *mode);
filename 參數(shù)是要打開的文件的路徑和名稱。mode 參數(shù)是一個字符串,用于指定文件的打開模式。常見的模式包括:
讀取模式 ("r")
含義:打開文件進(jìn)行讀取。操作:如果文件不存在,fopen 函數(shù)返回 NULL。文件指針定位在文件的開頭。 寫入模式 ("w")
含義:打開文件進(jìn)行寫入,如果文件存在則截斷文件(即清空文件),如果文件不存在則創(chuàng)建文件。操作:如果文件不存在,會創(chuàng)建一個新文件。如果文件已存在,打開時會清空文件的內(nèi)容。 追加模式 ("a")
含義:打開文件進(jìn)行寫入,如果文件存在則在文件末尾追加數(shù)據(jù),如果文件不存在則創(chuàng)建文件。操作:如果文件不存在,會創(chuàng)建一個新文件。文件指針定位在文件的末尾,寫入數(shù)據(jù)時會從文件末尾開始追加。 二進(jìn)制模式 ("b")
含義:以二進(jìn)制模式打開文件,通常與上述模式結(jié)合使用,如 "rb", "wb", "ab"。操作:在某些系統(tǒng)中,特別是在Windows中,二進(jìn)制模式可以確保文件內(nèi)容以二進(jìn)制方式讀取或?qū)懭?,而不會進(jìn)行換行符的轉(zhuǎn)換。 更新模式 ("+")(可與上述模式結(jié)合使用,如 "r+", "w+", "a+", "rb+", "wb+", "ab+")
含義:允許文件進(jìn)行讀寫操作,即可以讀取和寫入文件。操作:文件指針可以在文件中移動,讀取和寫入操作可以在文件中任意位置進(jìn)行(除了a+與ab+他們都是在文件末尾進(jìn)行寫入數(shù)據(jù)的)。
文件不存在時的情況
如果在打開文件時指定的模式不包括 w 或 a,而且文件不存在,fopen 函數(shù)將返回 NULL,表示文件打開失敗。例如,如果指定 "r" 模式打開一個不存在的文件,fopen 將返回 NULL,因?yàn)檫@種模式要求文件必須存在才能進(jìn)行讀取操作。在 "w" 和 "a" 模式下,如果文件不存在,fopen 函數(shù)會嘗試創(chuàng)建一個新文件。如果文件創(chuàng)建成功,它將打開并準(zhǔn)備進(jìn)行寫入操作。如果在打開時出現(xiàn)錯誤(如權(quán)限不足),則可能返回 NULL。
下面我們通過w模式進(jìn)行演示:
#include
int main()
{
//寫入
FILE* pflie = fopen("test.txt", "w");
//打開文件失敗,直接退出程序
if (pflie == NULL)
{
return 1;
}
//向文件寫入信息
fputs("abcdef", pflie);
fclose(pflie);
pflie = NULL;
return 0;
}
代碼解析:
如果沒有test.txt文件的話,會在當(dāng)前路徑地下創(chuàng)建一個新的文件test.txt如果原先有文件,文件的內(nèi)容會被清空,然后通過fputs向文件輸入信息.
4.3.2關(guān)閉文件
使用 fclose 函數(shù)關(guān)閉打開的文件。fclose 函數(shù)的原型如下:
int fclose(FILE *stream);
stream 參數(shù)是一個指向 FILE 結(jié)構(gòu)的指針,表示要關(guān)閉的文件
為什么要關(guān)閉文件?
關(guān)閉文件是一個重要的操作,有幾個關(guān)鍵的原因:
釋放資源:
操作系統(tǒng)為每個打開的文件分配了資源,包括內(nèi)存緩沖區(qū)和文件描述符等。如果不關(guān)閉文件,這些資源將一直占用,可能導(dǎo)致系統(tǒng)資源耗盡,特別是在處理大量文件或長時間運(yùn)行的程序中。 確保數(shù)據(jù)完整性:
在寫入文件時,數(shù)據(jù)通常首先存儲在內(nèi)存緩沖區(qū)中,并隨后被寫入到磁盤。如果不關(guān)閉文件,數(shù)據(jù)可能會停留在緩沖區(qū)中,而不會被完全寫入磁盤。這可能導(dǎo)致數(shù)據(jù)丟失或文件內(nèi)容不完整。 避免文件損壞:
如果文件在程序運(yùn)行時意外關(guān)閉(如程序崩潰),操作系統(tǒng)通常會確保文件被正確地關(guān)閉和保存。如果文件沒有被關(guān)閉,那么文件可能會處于打開狀態(tài),導(dǎo)致文件損壞或內(nèi)容丟失。 遵循最佳實(shí)踐:
關(guān)閉文件是良好的編程習(xí)慣和文件管理的一部分。這有助于保持代碼的清晰性和可維護(hù)性,并降低出現(xiàn)文件操作錯誤的可能性。
5.文件的順序讀寫
5.1 讀取文件
詳細(xì)說明
fgetc 函數(shù)
int fgetc(FILE *stream);
fgetc 函數(shù)(適用所有流):
作用: 從文件中讀取一個字符。返回值: 返回讀取的字符(強(qiáng)制轉(zhuǎn)換為 int 類型)。如果到達(dá)文件末尾或發(fā)生錯誤,返回 EOF。使用場景: 適用于逐個字符讀取的情況,例如讀取文本文件中的所有字符。
示例:
#include
int main() {
FILE *file = fopen("test.txt", "r");
if (file == NULL) {
perror("無法打開文件");
return 1;
}
int ch;
while ((ch = fgetc(file)) != EOF) {
putchar(ch); // 打印讀取的字符
}
fclose(file);
return 0;
}
fgets 函數(shù)
char *fgets(char *str, int n, FILE *stream);
fgets 函數(shù)(使用所有流):
作用: 從文件中讀取一行,最多讀取 n-1 個字符,并將這些字符存儲到 str 中。讀取的行以 '\0' 結(jié)尾。返回值: 如果成功,返回 str。如果到達(dá)文件末尾或發(fā)生錯誤,返回 NULL。使用場景: 適用于逐行讀取的情況,例如讀取配置文件或日志文件的每一行。
示例:
#include
int main() {
FILE *file = fopen("test.txt", "r");
if (file == NULL) {
perror("無法打開文件");
return 1;
}
char buffer[100];
while (fgets(buffer, sizeof(buffer), file) != NULL) {
printf("%s", buffer); // 打印讀取的行
}
fclose(file);
return 0;
}
fread函數(shù)
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
fread 函數(shù)從文件中讀取二進(jìn)制數(shù)據(jù),將其存儲到 ptr 指向的緩沖區(qū)中。size 是每個元素的大?。ㄒ宰止?jié)為單位),nmemb 是要讀取的元素數(shù)量。函數(shù)返回讀取的元素數(shù)量。
fread 函數(shù)(使用文件輸入流):
作用: 從文件中讀取二進(jìn)制數(shù)據(jù),將其存儲到 ptr 指向的緩沖區(qū)中。返回值: 返回成功讀取的元素數(shù)量。使用場景: 適用于讀取二進(jìn)制文件中的數(shù)據(jù),例如圖像文件或音頻文件。
示例:
#include
#include
int main() {
FILE *file = fopen("test.bin", "rb");
if (file == NULL) {
perror("無法打開文件");
return 1;
}
// 假設(shè)我們知道文件中有 10 個 int 類型的數(shù)據(jù)
int data[10];
size_t read_count = fread(data, sizeof(int), 10, file);
if (read_count != 10) {
perror("讀取數(shù)據(jù)時發(fā)生錯誤");
} else {
for (size_t i = 0; i < read_count; ++i) {
printf("%d ", data[i]);
}
printf("\n");
}
fclose(file);
return 0;
}
5.2寫入文件
1.fputc 函數(shù)
int fputc(int char, FILE *stream);
fputc 函數(shù)將一個字符寫入到指定的文件中。char 是要寫入的字符,stream 是文件指針。
返回值
成功時返回寫入的字符(強(qiáng)制轉(zhuǎn)換為 unsigned char 類型)。失敗時返回 EOF,并設(shè)置 errno 以指示錯誤。
示例
#include
int main() {
FILE *file = fopen("example.txt", "w");
if (file == NULL) {
perror("無法打開文件");
return 1;
}
fputc('A', file);
fputc('B', file);
fputc('C', file);
fclose(file);
return 0;
}
2.fputs 函數(shù)
int fputs(const char *str, FILE *stream);
fputs 函數(shù)將一個字符串寫入到指定的文件中。str 是要寫入的字符串,stream 是文件指針。
返回值
成功時返回非負(fù)值。失敗時返回 EOF,并設(shè)置 errno 以指示錯誤。
示例
#include
int main() {
FILE *file = fopen("example.txt", "w");
if (file == NULL) {
perror("無法打開文件");
return 1;
}
fputs("Hello, World!\n", file);
fputs("Welcome to C programming.\n", file);
fclose(file);
return 0;
}
3.fwrite 函數(shù)
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
fwrite 函數(shù)將二進(jìn)制數(shù)據(jù)寫入到指定的文件中。ptr 是源數(shù)據(jù)緩沖區(qū),size 是每個元素的大小(以字節(jié)為單位),nmemb 是要寫入的元素數(shù)量,stream 是文件指針。
返回值
成功時返回寫入的元素數(shù)量。失敗時返回一個小于 nmemb 的值,并設(shè)置 errno 以指示錯誤。
示例
#include
#include
int main() {
FILE *file = fopen("example.bin", "wb");
if (file == NULL) {
perror("無法打開文件");
return 1;
}
int data[] = {1, 2, 3, 4, 5};
size_t elements_written = fwrite(data, sizeof(int), 5, file);
if (elements_written != 5) {
perror("寫入數(shù)據(jù)時發(fā)生錯誤");
}
fclose(file);
return 0;
}
5.3fprintf printf sprintf fscanf scanf sscanf的使用
5.3.1fprintf、printf 和 sprintf 函數(shù)
這些函數(shù)用于格式化輸出。
1.fprintf
int fprintf(FILE *stream, const char *format, ...);
fprintf 將格式化的數(shù)據(jù)寫入到指定的文件流中。
參數(shù):
FILE *stream: 文件指針,指定輸出的文件。const char *format: 格式控制字符串。...: 可變參數(shù),指定要輸出的值。 返回值: 成功時返回寫入的字符數(shù),失敗時返回負(fù)值。
示例
#include
int main() {
FILE *file = fopen("output.txt", "w");
if (file == NULL) {
perror("無法打開文件");
return 1;
}
fprintf(file, "Name: %s, Age: %d\n", "Alice", 30);
fclose(file);
return 0;
}
2.printf
int printf(const char *format, ...);
printf 將格式化的數(shù)據(jù)輸出到標(biāo)準(zhǔn)輸出(通常是控制臺)。
參數(shù):
const char *format: 格式控制字符串。...: 可變參數(shù),指定要輸出的值。 返回值: 成功時返回寫入的字符數(shù),失敗時返回負(fù)值。
示例
#include
int main() {
printf("Name: %s, Age: %d\n", "Alice", 30);
return 0;
}
sprintf
int sprintf(char *str, const char *format, ...);
sprintf 將格式化的數(shù)據(jù)寫入到字符串中。
參數(shù):
char *str: 指向存儲結(jié)果的字符串的指針。const char *format: 格式控制字符串。...: 可變參數(shù),指定要輸出的值。 返回值: 成功時返回寫入的字符數(shù),失敗時返回負(fù)值。
示例
#include
int main() {
char buffer[100];
sprintf(buffer, "Name: %s, Age: %d\n", "Alice", 30);
printf("%s", buffer);
return 0;
}
5.3.2fscanf、scanf 和 sscanf 函數(shù)
這些函數(shù)用于格式化輸入。
1.fscanf
int fscanf(FILE *stream, const char *format, ...);
fscanf 從指定的文件流中讀取格式化的數(shù)據(jù)。
參數(shù):
FILE *stream: 文件指針,指定輸入的文件。const char *format: 格式控制字符串。...: 可變參數(shù),指向存儲讀取值的變量。 返回值: 成功讀取并賦值的項(xiàng)目數(shù),遇到錯誤或文件結(jié)束時返回 EOF。
示例
#include
int main() {
FILE *file = fopen("input.txt", "r");
if (file == NULL) {
perror("無法打開文件");
return 1;
}
//文件中,要有對應(yīng)的類型才能正確讀取
char name[50];
int age;
fscanf(file, "%s %d", name, &age);
printf("Name: %s, Age: %d\n", name, age);
fclose(file);
return 0;
}
2.scanf
int scanf(const char *format, ...);
scanf 從標(biāo)準(zhǔn)輸入(通常是鍵盤)讀取格式化的數(shù)據(jù)。
參數(shù):
const char *format: 格式控制字符串。...: 可變參數(shù),指向存儲讀取值的變量。 返回值: 成功讀取并賦值的項(xiàng)目數(shù),遇到錯誤或文件結(jié)束時返回 EOF。
示例
#include
int main() {
char name[50];
int age;
scanf("%s %d", name, &age);
printf("Name: %s, Age: %d\n", name, age);
return 0;
}
sscanf
int sscanf(const char *str, const char *format, ...);
sscanf 從字符串中讀取格式化的數(shù)據(jù)。
參數(shù) :
const char *str: 輸入字符串。const char *format: 格式控制字符串。...: 可變參數(shù),指向存儲讀取值的變量。 返回值: 成功讀取并賦值的項(xiàng)目數(shù),遇到錯誤時返回 EOF。
示例
#include
int main() {
char input[] = "Alice 30";
char name[50];
int age;
sscanf(input, "%s %d", name, &age);
printf("Name: %s, Age: %d\n", name, age);
return 0;
}
6.文件的隨機(jī)讀寫
6.1 fseek 函數(shù)
int fseek(FILE *stream, long int offset, int origin);
fseek 函數(shù)用于將文件指針移動到文件中的指定位置。
參數(shù)
FILE *stream: 文件指針,指定要操作的文件。 long int offset: 偏移量,以字節(jié)為單位,正值表示向文件末尾方向移動,負(fù)值表示向文件開頭方向移動。 int origin
: 指定移動的起始位置,可以是以下三個常量之一:
SEEK_SET: 文件開頭SEEK_CUR: 當(dāng)前位置SEEK_END: 文件末尾
返回值
成功時返回 0。失敗時返回非零值,并設(shè)置 errno 以指示錯誤。
示例
#include
int main() {
FILE *file = fopen("example.txt", "rb");
if (file == NULL) {
perror("無法打開文件");
return 1;
}
// 將文件指針移動到文件開頭之后的 10 個字節(jié)處
fseek(file, 10, SEEK_SET);
// 讀取當(dāng)前位置的字符
int ch = fgetc(file);
if (ch != EOF) {
printf("Character at position 10: %c\n", ch);
}
fclose(file);
return 0;
}
6.2ftell 函數(shù)
long int ftell(FILE *stream);
ftell 函數(shù)用于獲取文件指針當(dāng)前的位置(相對于文件開頭的字節(jié)偏移量)。
參數(shù)
FILE *stream: 文件指針,指定要操作的文件。
返回值
成功時返回文件指針的當(dāng)前位置(以字節(jié)為單位的偏移量)。失敗時返回 -1L,并設(shè)置 errno 以指示錯誤。
示例
#include
int main() {
FILE *file = fopen("example.txt", "rb");
if (file == NULL) {
perror("無法打開文件");
return 1;
}
// 將文件指針移動到文件開頭之后的 10 個字節(jié)處
fseek(file, 10, SEEK_SET);
// 獲取文件指針的當(dāng)前位置
long int position = ftell(file);
if (position != -1L) {
printf("Current position: %ld\n", position);
}
fclose(file);
return 0;
}
6.2 rewind 函數(shù)
void rewind(FILE *stream);
rewind 函數(shù)將文件指針重新定位到文件的開頭,并清除文件指針的錯誤和 EOF 狀態(tài)。
參數(shù)
FILE *stream: 文件指針,指定要操作的文件。
示例
#include
int main() {
FILE *file = fopen("example.txt", "rb");
if (file == NULL) {
perror("無法打開文件");
return 1;
}
// 將文件指針移動到文件開頭之后的 10 個字節(jié)處
fseek(file, 10, SEEK_SET);
// 使用 rewind 函數(shù)將文件指針重新定位到文件開頭
rewind(file);
// 獲取文件指針的當(dāng)前位置
long int position = ftell(file);
if (position != -1L) {
printf("Current position after rewind: %ld\n", position);
}
fclose(file);
return 0;
}
7.文件讀取結(jié)束的判定
7.1feof函數(shù)的使用
feof 函數(shù)
int feof(FILE *stream);
feof 函數(shù)用于檢查文件指針是否已經(jīng)到達(dá)文件末尾(EOF)。
參數(shù)
FILE *stream: 文件指針,指定要檢查的文件。
返回值
如果文件指針到達(dá)文件末尾,則返回非零值(通常是 1)。如果文件指針未到達(dá)文件末尾,則返回零。
使用場景
feof 函數(shù)通常在讀取文件的循環(huán)中使用,以便檢測何時到達(dá)文件末尾,從而終止讀取操作。
示例
#include
int main() {
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
perror("無法打開文件");
return 1;
}
int ch;
while ((ch = fgetc(file)) != EOF) {
putchar(ch);
}
if (feof(file)) {
printf("\n已到達(dá)文件末尾。\n");
} else {
printf("\n讀取文件時發(fā)生錯誤。\n");
}
fclose(file);
return 0;
}
詳細(xì)說明
作用: feof 函數(shù)檢查文件指針是否到達(dá)文件末尾。這在文件讀取過程中非常有用,可以防止讀取超出文件內(nèi)容。使用方法:
打開文件。讀取文件內(nèi)容,在讀取操作中檢查是否到達(dá)文件末尾。根據(jù) feof 的返回值確定是否已到達(dá)文件末尾。
注意事項(xiàng)
feof 僅在嘗試讀取文件并且讀取操作返回 EOF 后,才會返回非零值。因此,必須在讀取操作失?。ǚ祷?EOF)之后調(diào)用 feof,才能正確判斷是否到達(dá)文件末尾。如果讀取操作由于其他原因失敗(例如文件錯誤),feof 也可能返回零。在這種情況下,應(yīng)檢查其他文件錯誤狀態(tài),例如通過 ferror 函數(shù)
feof 與 ferror 結(jié)合使用
為了更準(zhǔn)確地處理文件讀取錯誤,通常將 feof 與 ferror 結(jié)合使用,以區(qū)分文件末尾和讀取錯誤。
示例
#include
int main() {
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
perror("無法打開文件");
return 1;
}
int ch;
while ((ch = fgetc(file)) != EOF) {
putchar(ch);
}
if (feof(file)) {
printf("\n已到達(dá)文件末尾。\n");
} else if (ferror(file)) {
printf("\n讀取文件時發(fā)生錯誤。\n");
}
fclose(file);
return 0;
}
8.文件緩沖區(qū)
文件緩沖區(qū)是一塊內(nèi)存,用于臨時存儲從文件讀取的數(shù)據(jù)或準(zhǔn)備寫入到文件的數(shù)據(jù)。數(shù)據(jù)在緩沖區(qū)填滿后才會實(shí)際寫入文件。讀取操作也是在緩沖區(qū)為空時才會實(shí)際從文件中讀取數(shù)據(jù)。緩沖區(qū)提高了文件讀寫操作的效率,因?yàn)樗鼫p少了直接與磁盤交互的次數(shù)。
圖示:
使用fflush刷新緩沖區(qū):
#include
#include
int main() {
FILE* file = fopen("example1.txt", "w");
if (file == NULL) {
perror("無法打開文件");
return 1;
}
fputs("刷新緩沖區(qū)", file);
//睡眠10秒,我們這時候看文件中,是沒有內(nèi)容的
Sleep(10000);
//沒刷新緩沖區(qū)前.數(shù)據(jù)不會寫到文件中
fflush(file);
Sleep(1000);
//fclose關(guān)閉文件的時候,也會刷新緩沖區(qū)
fclose(file);
return 0;
}
磊結(jié)語
通過本文的學(xué)習(xí),我們詳細(xì)了解了C語言中文件操作的基礎(chǔ)知識和實(shí)際應(yīng)用。文件操作不僅限于簡單的讀寫,它還涉及到如何有效地管理內(nèi)存和磁盤資源,以及如何處理各種異常情況和錯誤。掌握好文件操作的技能,不僅可以提升我們的編程效率,還能夠讓我們更加深入地理解計算機(jī)系統(tǒng)的底層工作原理。希望本文能夠幫助讀者建立起堅實(shí)的文件操作基礎(chǔ),并在實(shí)際項(xiàng)目中得到應(yīng)用和延展。
柚子快報邀請碼778899分享:開發(fā)語言 C語言-文件操作
好文閱讀
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。