最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語(yǔ)言文件隨機(jī)讀寫的完全指南

 更新時(shí)間:2025年10月18日 09:23:40   作者:蒙奇D索大  
本文詳細(xì)介紹了C語(yǔ)言中實(shí)現(xiàn)文件隨機(jī)讀寫的關(guān)鍵函數(shù)(fseek, ftell, rewind)及其應(yīng)用,通過(guò)移動(dòng)文件光標(biāo),隨機(jī)讀寫允許直接訪問(wèn)文件的任意位置,適用于數(shù)據(jù)庫(kù)、日志文件等場(chǎng)景,需要的朋友可以參考下

導(dǎo)讀

無(wú)論是字符級(jí)的 fgetc/fputc,字符串操作的 fgets/fputs,還是格式化的 fscanf/fprintf,以及二進(jìn)制的 fread/fwrite,這些函數(shù)都遵循著"從頭到尾、依次處理"的順序讀寫模式。

然而,在實(shí)際編程中,我們常常需要更靈活的文件操作方式。今天,我們將進(jìn)入文件操作的另一個(gè)重要領(lǐng)域——隨機(jī)讀寫,學(xué)習(xí)如何精準(zhǔn)控制文件中的讀寫位置。讓我們開始探索以下五個(gè)核心函數(shù):

  • fseek —— 設(shè)置文件中的位置指示器位置
  • ftell —— 獲取文件中的位置指示器位置
  • rewind —— 重置文件中的位置指示器位置
  • fgetpos —— 獲取文件中的位置指示器位置
  • fsetpos —— 設(shè)置文件中的位置指示器位置

一、fseek

fseek

上圖給出了函數(shù)用法的介紹,我們可以看到該函數(shù)不僅能夠?qū)ξ谋疚募褂茫€可以對(duì)二進(jìn)制文件使用;

fseek2

上圖給我們介紹了函數(shù)的三個(gè)參數(shù)與返回值,從這兩張圖片介紹中,我們可以了解該函數(shù)的使用方法:

  • 向函數(shù)中傳入3個(gè)參數(shù)
    • stream :指向識(shí)別流的 FILE 對(duì)象指針
    • offset :文件中光標(biāo)的位置
      • 二進(jìn)制文件中:從 origin 的參考值中偏移的字節(jié)數(shù)
      • 文本文件中:0 或者由 ftell 函數(shù)獲取的返回值
    • origin :為 offset 參考的位置
      • SEEK_SET : 文件開頭
      • SEEK_CUR :文件指針的當(dāng)前位置
      • SEEK_END :文件末尾
  • 函數(shù)會(huì)將與流關(guān)聯(lián)的文件內(nèi)部的光標(biāo)設(shè)置為一個(gè)新位置:
    • 二進(jìn)制文件:新位置由 origin 的參考位置的偏移量 offset 定義
    • 文本文件:新位置為 0 或者由先前調(diào)用 ftell 函數(shù)時(shí)的返回值,并且 origin 的參考值必須為 SEEK_SET ,即文件開頭;
    • 當(dāng)函數(shù)在這些參考值之外調(diào)用其他值,是否支持還取決于特定的系統(tǒng)和庫(kù)的實(shí)現(xiàn)。即若當(dāng)前系統(tǒng)支持,那此時(shí)的使用方法無(wú)法移植。
  • 函數(shù)在完成設(shè)置后,會(huì)給出相應(yīng)的返回值:
    • 設(shè)置成功,則函數(shù)返回 0
    • 設(shè)置失敗,則函數(shù)返回非零值
    • 如果發(fā)生讀取或?qū)懭脲e(cuò)誤,則函數(shù)會(huì)設(shè)置錯(cuò)誤指示器(ferror

從用法中我們可以看到,該函數(shù)的使用與 ftell 函數(shù)是分不開的,因此我們下面直接來(lái)看一下 ftell 函數(shù)應(yīng)該如何使用;

二、ftell

2.1 函數(shù)介紹

ftell

該函數(shù)的使用方法為:

  • 向函數(shù)中傳入一個(gè)參數(shù):
    • stream :指向識(shí)別流的 FILE 對(duì)象指針
  • 函數(shù)會(huì)從流中獲取當(dāng)前位置指示器的值
    • 成功時(shí),則將當(dāng)前值返回
    • 失敗時(shí),則返回 -1L ,并將 errno 設(shè)置為系統(tǒng)的特定正值

2.2 函數(shù)使用

該函數(shù)的使用我們可以簡(jiǎn)單的理解為,函數(shù)會(huì)獲取文件中的光標(biāo)位置:

  • 當(dāng)文件為二進(jìn)制文件時(shí),函數(shù)的返回值為文件光標(biāo)從文件開頭開始的偏移量
  • 當(dāng)文件為文本文件時(shí),函數(shù)的返回值可能沒有實(shí)際意義,但是仍可在調(diào)用 fseek 時(shí)作為函數(shù)參數(shù),讓 fseek 將光標(biāo)的位置恢復(fù)到當(dāng)前位置

現(xiàn)在對(duì)于 fseek 和 ftell 這兩個(gè)函數(shù)我們就能夠理解為:

  • ftell 用于獲取文件中的光標(biāo)位置
  • fseek 用于設(shè)置文件中的光標(biāo)位置

接下來(lái)我們就可以嘗試著使用這兩個(gè)函數(shù)了:

void test1() {
	FILE* pf = fopen("C:\\Users\\LIQIAN\\Desktop\\data.txt", "r+");
	if (pf == NULL) {
		perror("fopen");
		return;
	}

	// 通過(guò) ftell 獲取文件中的光標(biāo)當(dāng)前位置
	long int index = ftell(pf);
	// 檢查返回值
	if (index == -1L) {
		perror("ftell");
		fclose(pf);
		pf = NULL;
		return;
	}

	// 通過(guò) fgetc 讀取當(dāng)前位置的文本信息
	int ch = fgetc(pf);
	while (ch != EOF) {
		printf("ch = %c\n", ch);
		ch = fgetc(pf);
	}

	// 通過(guò) fseek 設(shè)置文件中的光標(biāo)位置
	int set = fseek(pf, index, SEEK_SET);
	// 由于我們打開的為文本文件,因此 origin 的值必須為文件開頭(SEEK_SET)

	if (set != 0) {
		perror("fseek");
		fclose(pf);
		pf = NULL;
		return;
	}

	// 再一次讀取當(dāng)前位置的元素
	ch = fgetc(pf);
	printf("ch = %c\n", ch);

	fclose(pf);
	pf = NULL;
}

這里的測(cè)試代碼邏輯比較簡(jiǎn)單:

  • 先通過(guò) ftell 記錄文件當(dāng)前的光標(biāo)起始位置
  • 通過(guò) fgetc 進(jìn)行內(nèi)容讀取,直到光標(biāo)移動(dòng)到文件末尾
  • 之后通過(guò) fseek 重新設(shè)置光標(biāo)的位置
  • 最后再一次通過(guò) fgetc 來(lái)讀取當(dāng)前位置的內(nèi)容

下面我們就來(lái)運(yùn)行以下該測(cè)試代碼:

函數(shù)使用

從測(cè)試結(jié)果中可以看到,文件剛打開時(shí),光標(biāo)的位置為文件開頭,當(dāng)我們通過(guò) ftell 記錄了此時(shí)的位置后,我們通過(guò) fgetc 移動(dòng)了光標(biāo),不管光標(biāo)最后在哪里,我們都可以通過(guò) fseek 函數(shù)將光標(biāo)設(shè)置到最初我們記錄的位置;

那可能有朋友會(huì)問(wèn),如果我們?cè)谟涗浌鈽?biāo)的起始位置時(shí),光標(biāo)并不在文件開頭,這時(shí)我們需要將光標(biāo)重置到文件開頭,應(yīng)該怎么辦呢?

此時(shí)有兩種辦法:

  • 通過(guò)將 offset 參數(shù)值置為 0 ,即 int set = fseek(pf, 0, SEEK_SET);
  • 通過(guò) rewind 函數(shù)重置光標(biāo)位置

接下來(lái),我們就來(lái)看看 rwind 函數(shù)的具體用法;

三、rewind

3.1 函數(shù)介紹

函數(shù)介紹

該函數(shù)的用法如下:

  • 向函數(shù)中傳入一個(gè)參數(shù):
    • stream :指向標(biāo)識(shí)流的 FILE 對(duì)象指針
  • 函數(shù)會(huì)清除流中的文件末尾內(nèi)部指示器錯(cuò)誤內(nèi)部指示器,并將文件內(nèi)部的位置指示器設(shè)置為文件開頭

3.2 函數(shù)使用

該函數(shù)簡(jiǎn)單的理解就是用于重置文件內(nèi)部的光標(biāo)位置。接下來(lái)我們就來(lái)對(duì)其進(jìn)行測(cè)試:

void test2() {
	FILE* pf = fopen("C:\\Users\\LIQIAN\\Desktop\\data.txt", "r+");
	if (pf == NULL) {
		perror("fopen");
		return;
	}

	// 通過(guò) fgetc 先讀取一定的文本信息
	for (int i = 0; i < 3; i++) {
		int ch = fgetc(pf);
		printf("ch = %c ", ch);
	}
	printf("\n");

	// 通過(guò) ftell 獲取文件中的光標(biāo)當(dāng)前位置
	long int index = ftell(pf);
	// 檢查返回值
	if (index == -1L) {
		perror("ftell");
		fclose(pf);
		pf = NULL;
		return;
	}

	// 通過(guò) fgetc 讀取當(dāng)前位置的文本信息
	int ch = fgetc(pf);
	while (ch != EOF) {
		printf("ch = %c ", ch);
		ch = fgetc(pf);
	}
	printf("\n");

	// 通過(guò) fseek 設(shè)置文件中的光標(biāo)位置
	int set = fseek(pf, index, SEEK_SET);
	// 由于我們打開的為文本文件,因此 origin 的值必須為文件開頭(SEEK_SET)

	if (set != 0) {
		perror("fseek");
		fclose(pf);
		pf = NULL;
		return;
	}

	// 再一次讀取當(dāng)前位置的元素
	ch = fgetc(pf);
	printf("ch = %c\n", ch);

	// 通過(guò) rewind 重置光標(biāo)位置
	rewind(pf);

	// 再一次讀取當(dāng)前位置的元素
	ch = fgetc(pf);
	printf("ch = %c\n", ch);

	fclose(pf);
	pf = NULL;
}

我們此時(shí)的測(cè)試邏輯很簡(jiǎn)單:

  • 文件在打開時(shí),光標(biāo)會(huì)位于文件開頭
  • 首先,我們通過(guò) fgetc 讀取數(shù)據(jù)來(lái)移動(dòng)光標(biāo)
  • 完成寫入后,通過(guò) ftell 來(lái)記錄光標(biāo)此時(shí)的位置
  • 接下來(lái),我們繼續(xù)通過(guò) fgetc 讀取數(shù)據(jù),進(jìn)一步移動(dòng)光標(biāo)
  • 之后,我們?cè)偻ㄟ^(guò) fseek 來(lái)恢復(fù)光標(biāo)的位置
  • 最后,我們?cè)偻ㄟ^(guò) rewind 來(lái)重置光標(biāo)的位置

下面我們就來(lái)對(duì)其測(cè)試一下:

函數(shù)使用

可以看到,當(dāng)我們使用 rewind 后,光標(biāo)的位置就從我們最開始記錄的 l 處重置為了文件開頭 H 處。

因此當(dāng)我們?cè)趯?duì)文件進(jìn)行操作時(shí),如果我們需要重置光標(biāo)的位置,我們就可以通過(guò) rewind 實(shí)現(xiàn)。

四、fgetpos

4.1 函數(shù)介紹

fgetpos

該函數(shù)的用法如下所示:

  • 向函數(shù)中傳入兩個(gè)參數(shù):
    • stream :指向標(biāo)識(shí)流的 FILE 對(duì)象指針
    • pos :指向 fpos_t 對(duì)象指針
  • 函數(shù)會(huì)將從 stream 中獲取到的當(dāng)前位置信息填入到 pos 中
    • 成功時(shí),函數(shù)返回 0
    • 發(fā)生錯(cuò)誤時(shí),errno 會(huì)被設(shè)置為平臺(tái)特定的正值,并且函數(shù)返回一個(gè)非零值

4.2 fpos_t

在函數(shù)的用法介紹中,我們看到了一個(gè)新的類型:fpos_t 。那么在使用該函數(shù)前,我們先來(lái)認(rèn)識(shí)一下這個(gè)新的類型:

fpos_t

該類型就是專門用于記錄文件中的光標(biāo)位置的類型,該類型的變量中存儲(chǔ)的信息,通常是通過(guò) fgetpos 函數(shù)進(jìn)行填充,并且其變量中的信息不能直接讀取,只能夠在調(diào)用 fsetpos 時(shí),作為參數(shù)使用。

那也就是說(shuō),fgetposfsetpos 這兩個(gè)函數(shù)應(yīng)該搭配起來(lái)使用,那么接下來(lái)我們就一起來(lái)看看如何 fsetpos 的具體用法;

五、fsetpos

5.1 函數(shù)介紹

fsetpos

該函數(shù)的用法如下所示:

  • 向函數(shù)中傳入兩個(gè)參數(shù):
    • stream :指向標(biāo)識(shí)流的 FILE 對(duì)象指針
    • pos :指向 fpos_t 對(duì)象指針
  • 函數(shù)會(huì)將 stream 的當(dāng)前位置恢復(fù)到 pos 中
    • 成功時(shí),函數(shù)返回 0
    • 發(fā)生錯(cuò)誤時(shí),errno 會(huì)被設(shè)置為平臺(tái)特定的正值,并且函數(shù)返回一個(gè)非零值

5.2 函數(shù)使用

該函數(shù)的用法我們可以簡(jiǎn)單的理解為,將文件中的光標(biāo)位置恢復(fù)到 pos 中存儲(chǔ)的位置。

這里需要注意的是,pos_t 的對(duì)象中存儲(chǔ)的信息只能通過(guò) fgetpos 獲取,我們無(wú)法直接對(duì)其進(jìn)行賦值操作?。?!

接下來(lái)我們就來(lái)嘗試著使用一下這兩個(gè)函數(shù):

void test3() {
	FILE* pf = fopen("C:\\Users\\LIQIAN\\Desktop\\data.txt", "r");
	if (pf == NULL) {
		perror("fopen");
		return;
	}

	// 通過(guò) fgetc 讀取數(shù)據(jù)來(lái)移動(dòng)光標(biāo)
	for (int i = 0; i < 3; i++) {
		int ch = fgetc(pf);
		printf("ch = %c\n", ch);
	}
	printf("\n");
	// 記錄光標(biāo)位置變量
	fpos_t pos;

	// 通過(guò) fgetpos 獲取當(dāng)前光標(biāo)位置
	int get = fgetpos(pf, &pos);

	// 通過(guò) fgetc 移動(dòng)光標(biāo)
	int ch = fgetc(pf);
	while (ch != '!') {
		printf("ch = %c\n", ch);
		ch = fgetc(pf);
	}

	printf("\nch = %c\n", ch);

	// 通過(guò) fsetpos 來(lái)恢復(fù)光標(biāo)位置
	int set = fsetpos(pf, &pos);
	
	ch = fgetc(pf);
	printf("\nch = %c\n", ch);

	fclose(pf);
	pf = NULL;
}

這一次我們測(cè)試的邏輯與前面的邏輯一致:

  • 先通過(guò) fgetc 來(lái)移動(dòng)光標(biāo)
  • 再通過(guò) fgetpos 來(lái)獲取光標(biāo)位置信息
  • 之后再一次通過(guò) fgetc 來(lái)移動(dòng)光標(biāo)
  • 最后通過(guò) fsetpos 來(lái)設(shè)置光標(biāo)位置

下面我們就來(lái)測(cè)試一下:

函數(shù)使用

可以看到,函數(shù) fgetposfsetpos 二者配合起來(lái)使用,同樣能夠達(dá)到光標(biāo)定位與設(shè)置的效果。

現(xiàn)在問(wèn)題來(lái)了,這兩個(gè)函數(shù)與前面我們介紹的 ftellfseek 之間有什么不同呢?

5.3 函數(shù)比較

5.3.1 相同點(diǎn)

不管是 ftell 與 fseek 的搭配使用,還是 fgetpos 與 fsetpos 的搭配使用,他們都是用來(lái)完成兩件事:

  • 記錄光標(biāo)位置
  • 設(shè)置光標(biāo)位置

5.3.2 不同點(diǎn)

這二者之間不同的地方在于—— 記錄光標(biāo)位置的方式不同

  • ftell 是通過(guò) long int 類型的變量來(lái)記錄光標(biāo)的位置
  • fgetpos 則是通過(guò) fpos_t 類型的變量來(lái)記錄光標(biāo)位置

因此,這就導(dǎo)致了二者能夠處理的文件大小有所區(qū)別:

  • 當(dāng)光標(biāo)的位置值大于 long int 時(shí),我們?cè)偻ㄟ^(guò) ftell 來(lái)記錄光標(biāo)的位置就會(huì)出現(xiàn)問(wèn)題
  • 由于 fgetpos 是通過(guò) fpos_t 來(lái)記錄,因此,我們不需要考慮光標(biāo)的位置是否會(huì)存在溢出的情況

也就是說(shuō),當(dāng)我們處理大文件時(shí),我們選擇使用 fgetposfsetpos 會(huì)更加保險(xiǎn)一點(diǎn)。

結(jié)語(yǔ)

通過(guò)今天的學(xué)習(xí),我們深入掌握了C語(yǔ)言中實(shí)現(xiàn)文件隨機(jī)讀寫的五個(gè)核心函數(shù)。讓我們簡(jiǎn)單回顧一下本篇的重要內(nèi)容:

函數(shù)功能總結(jié)

  • fseek:精確定位文件光標(biāo),支持三種參考位置(文件頭、當(dāng)前位置、文件尾)
  • ftell:獲取當(dāng)前光標(biāo)位置,為 fseek 提供定位依據(jù)
  • rewind:快速重置光標(biāo)到文件開頭,并清除錯(cuò)誤指示器
  • fgetpos:使用fpos_t類型安全記錄光標(biāo)位置
  • fsetpos:與 fgetpos 配合,精準(zhǔn)恢復(fù)光標(biāo)位置

關(guān)鍵區(qū)別:

  • ftell/fseek 使用 long 類型,適合一般文件操作
  • fgetpos/fsetpos 使用 fpos_t 類型,更適合大文件處理

實(shí)踐價(jià)值

掌握了這些函數(shù),我們就能在文件中自由"穿梭",實(shí)現(xiàn)高效的隨機(jī)訪問(wèn),為復(fù)雜文件操作打下堅(jiān)實(shí)基礎(chǔ)。

以上就是C語(yǔ)言文件隨機(jī)讀寫的完全指南的詳細(xì)內(nèi)容,更多關(guān)于C語(yǔ)言文件隨機(jī)讀寫的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • c++中的字節(jié)序與符號(hào)位的問(wèn)題

    c++中的字節(jié)序與符號(hào)位的問(wèn)題

    這篇文章主要介紹了c++中的字節(jié)序與符號(hào)位的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • C#委托所蘊(yùn)含的函數(shù)指針概念詳細(xì)解析

    C#委托所蘊(yùn)含的函數(shù)指針概念詳細(xì)解析

    C#中用委托這種概念實(shí)現(xiàn)了函數(shù)指針技術(shù)而已,另外.ent提供額外的安全性,當(dāng)然也損失了靈活性
    2013-09-09
  • 使用VS2019編譯CEF2623項(xiàng)目的libcef_dll_wrapper.lib的方法

    使用VS2019編譯CEF2623項(xiàng)目的libcef_dll_wrapper.lib的方法

    這篇文章主要介紹了使用VS2019編譯CEF2623項(xiàng)目的libcef_dll_wrapper.lib的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • 關(guān)于C++11中限定作用域的枚舉類型的問(wèn)題

    關(guān)于C++11中限定作用域的枚舉類型的問(wèn)題

    C++中有兩種類型的枚舉:不限定作用域的枚舉類型和限定作用域的枚舉類型。限定作用域的枚舉類型是C++11標(biāo)準(zhǔn)引入的新類型,對(duì)C++11中限定作用域的枚舉類型相關(guān)知識(shí)感興趣的朋友一起看看吧
    2022-01-01
  • C語(yǔ)言實(shí)現(xiàn)控制臺(tái)五子棋小游戲

    C語(yǔ)言實(shí)現(xiàn)控制臺(tái)五子棋小游戲

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)控制臺(tái)五子棋小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • 簡(jiǎn)單總結(jié)C語(yǔ)言中各種類型的指針的概念

    簡(jiǎn)單總結(jié)C語(yǔ)言中各種類型的指針的概念

    這篇文章主要簡(jiǎn)單總結(jié)了C語(yǔ)言中各種類型的指針的概念,指針可以說(shuō)是C語(yǔ)言本身所具有的最大特性,平時(shí)根據(jù)不同使用場(chǎng)合習(xí)慣地將其簡(jiǎn)單分類,需要的朋友可以參考下
    2016-03-03
  • C語(yǔ)言使用libZPlay錄制聲音并寫到文件的方法

    C語(yǔ)言使用libZPlay錄制聲音并寫到文件的方法

    這篇文章主要介紹了C語(yǔ)言使用libZPlay錄制聲音并寫到文件的方法,實(shí)例分析了C語(yǔ)言操作音頻文件的相關(guān)技巧,需要的朋友可以參考下
    2015-06-06
  • VS?Code?C++?環(huán)境配置及?HelloWorld?程序(保姆教程)

    VS?Code?C++?環(huán)境配置及?HelloWorld?程序(保姆教程)

    文章詳細(xì)介紹了在Windows、macOS和Linux上配置VSCode的C++開發(fā)環(huán)境,并提供了創(chuàng)建、編譯、調(diào)試和使用CMake的步驟,還涵蓋了常見問(wèn)題的解決方法和快速模板項(xiàng)目的獲取,感興趣的朋友跟隨小編一起看看吧
    2025-12-12
  • C++異常處理入門(try和catch)

    C++異常處理入門(try和catch)

    C++ 提供了異常機(jī)制,讓我們能夠捕獲運(yùn)行時(shí)錯(cuò)誤,本文就詳細(xì)的介紹了C++異常處理入門,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • C++11 花括號(hào)等式初始化器的使用

    C++11 花括號(hào)等式初始化器的使用

    花括號(hào)等式初始化器是C++11引入的一項(xiàng)強(qiáng)大特性,它為開發(fā)者提供了一種統(tǒng)一、簡(jiǎn)潔且安全的方式來(lái)初始化對(duì)象,本文就來(lái)介紹一下花括號(hào)等式初始化器的具體使用,感興趣的可以了解一下
    2025-06-06

最新評(píng)論

兴文县| 扶余县| 五常市| 山东省| 阳高县| 陆川县| 车险| 建始县| 浑源县| 朔州市| 湖北省| 遂川县| 南昌县| 冕宁县| 和硕县| 赤城县| 霍林郭勒市| 布尔津县| 桂林市| 文山县| 陇南市| 黄大仙区| 长治县| 涿鹿县| 武威市| 屯门区| 万源市| 东海县| 海兴县| 腾冲县| 汨罗市| 新余市| 曲周县| 湖北省| 耿马| 北川| 石门县| 清河县| 冀州市| 方城县| 玉溪市|