溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

C語(yǔ)言如何實(shí)現(xiàn)隨機(jī)讀寫(xiě)文件

發(fā)布時(shí)間:2023-03-31 15:25:13 來(lái)源:億速云 閱讀:95 作者:iii 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要講解了“C語(yǔ)言如何實(shí)現(xiàn)隨機(jī)讀寫(xiě)文件”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“C語(yǔ)言如何實(shí)現(xiàn)隨機(jī)讀寫(xiě)文件”吧!

1.fseek

前面已經(jīng)劇透過(guò)了,fseek可以改變記錄讀寫(xiě)位置的指針的指向,從而實(shí)現(xiàn)文件的隨機(jī)讀寫(xiě)。該函數(shù)的聲明如下:

int fseek ( FILE * stream, long int offset, int origin );

第一個(gè)參數(shù)大家都很熟悉了,就是一個(gè)文件指針,告訴fseek我現(xiàn)在操作的是哪個(gè)文件。

第二個(gè)參數(shù),offset是偏移量的意思,大家先記住。第三個(gè)參數(shù),origin,顧名思義,即“起始位置”。后面兩個(gè)參數(shù)讓人摸不著頭腦,但是配合起來(lái)就很有意思了。

舉個(gè)例子:假設(shè)一個(gè)文件中存有abcdefg,當(dāng)你用fopen打開(kāi)這個(gè)文件時(shí),一個(gè)記錄讀寫(xiě)位置的指針就指向了起始位置,也就是指向了a。如果我想讀取第5個(gè)字符,即e呢?那我就要讓這個(gè)指針指向e,這樣再fgetc就能讀到e了。

我可以這樣算:e相對(duì)于起始位置a,向右偏移了4個(gè)字符,因?yàn)橄鄬?duì)于a,a自己的偏移量是0,b是1,c是2,d是3,e自然是4。那么,偏移量offset(fseek的第二個(gè)參數(shù))就是4,這個(gè)4是相對(duì)于起始位置的,這個(gè)“相對(duì)于”哪里,也就是origin(fseek的第三個(gè)參數(shù))的位置,此時(shí)origin就是“起始位置”,明白了吧。而fseek用一個(gè)宏SEEK_SET來(lái)表示“起始位置”,所以此時(shí)fseek的調(diào)用如下:

fseek(pf, 4, SEEK_SET);

下面我們來(lái)驗(yàn)證一下。先在工程目錄下創(chuàng)建一個(gè)文件,文件名是test.txt,然后在里面輸入abcdefg。

C語(yǔ)言如何實(shí)現(xiàn)隨機(jī)讀寫(xiě)文件

按照打開(kāi)文件->讀文件->關(guān)閉文件的順序,寫(xiě)代碼:

#include <stdio.h>

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	fseek(pf, 4, SEEK_SET);
	putchar(fgetc(pf));

	fclose(pf);
	pf = NULL;

	return 0;
}

打開(kāi)文件后,使用fseek讓記錄讀寫(xiě)位置的指針指向e,接著用fgetc讀取e并用putchar打印出來(lái),輸出結(jié)果如下:

C語(yǔ)言如何實(shí)現(xiàn)隨機(jī)讀寫(xiě)文件

我們就成功跳過(guò)了前面的abcd,直接讀取到e,實(shí)現(xiàn)了文件的隨機(jī)讀寫(xiě)。

當(dāng)然,讀取到e不止有這一種寫(xiě)法。fseek的第三個(gè)參數(shù)origin有三種取值,分別是:

1.SEEK_SET,表示起始位置。

2.SEEK_CUR,表示當(dāng)前指向的位置。

3.SEEK_END,表示文件末尾。

SEEK_SET和SEEK_CUR都很好理解,需要注意的是,SEEK_END不是指向最后一個(gè)字符,而是指向最后一個(gè)字符的下一個(gè)位置。比如,一個(gè)文件中存有abcdefg,SEEK_END不是指向g,而是指向g的下一個(gè)位置。所以同樣是讀到e,如果origin是SEEK_END,offset就應(yīng)該是-3,因?yàn)間的偏移量是-1,f是-2,所以e是-3。把上面代碼中的fseek的調(diào)用方式改一下,其他不變:

fseek(pf, -3, SEEK_END);

也可以讀到e,因?yàn)樵趫?zhí)行完上面這行代碼后,記錄讀寫(xiě)位置的指針就指向了e,所以讀取時(shí)就跳過(guò)了前面的abcd,直接讀到e。說(shuō)明一下,由于讀寫(xiě)前該指針指向了e,調(diào)用fgetc讀完e后,該指針就指向了e后面的f,也就是說(shuō),此時(shí)SEEK_CUR就指向了f,如果我們想讀到b呢?可以數(shù)一下,abcdefg,b相對(duì)于SEEK_CUR(指向f)的偏移量就是-4,如果像下面的代碼這樣寫(xiě):

#include <stdio.h>

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	fseek(pf, -3, SEEK_END); // 指向e
	putchar(fgetc(pf)); // 讀完e后指向f

	fseek(pf, -4, SEEK_CUR); // 指向b
	putchar(fgetc(pf)); // 讀完b后指向c

	fclose(pf);
	pf = NULL;

	return 0;
}

輸出結(jié)果如下:

C語(yǔ)言如何實(shí)現(xiàn)隨機(jī)讀寫(xiě)文件

2.ftell

我如果想知道此時(shí)記錄讀寫(xiě)位置的指針相對(duì)于起始位置的偏移量(即相對(duì)于SEEK_SET的偏移量)是多少,就可以問(wèn)問(wèn)ftell函數(shù)。該函數(shù)聲明如下:

long int ftell ( FILE * stream );

ftell會(huì)返回當(dāng)前相對(duì)于起始位置的偏移量。比如前面的例子中調(diào)用:

#include <stdio.h>

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	fseek(pf, -3, SEEK_END); // 指向e
	putchar(fgetc(pf)); // 讀完e后指向f

	fseek(pf, -4, SEEK_CUR); // 指向b
	putchar(fgetc(pf)); // 讀完b后指向c

	printf("\n%ld\n", ftell(pf));

	fclose(pf);
	pf = NULL;

	return 0;
}

由于此時(shí)記錄文件讀寫(xiě)位置的指針指向了c,偏移量是2(a為0,b為1,c為2),所以會(huì)輸出2。

C語(yǔ)言如何實(shí)現(xiàn)隨機(jī)讀寫(xiě)文件

3.rewind

rewind的作用是,讓指向文件讀寫(xiě)位置的指針指向文件的起始位置。該函數(shù)聲明如下:

void rewind ( FILE * stream );

其實(shí)非常簡(jiǎn)單,rewind(pf);和fseek(pf, 0, SEEK_SET);是等價(jià)的。

在前面的例子中,記錄文件讀寫(xiě)位置的指針左右橫跳,最后指向了c,此時(shí)ftell也返回了2,這時(shí)如果我rewind一下,該指針就又指向了起始位置,即a,再ftell就能知道偏移量回到了0,如果再fgetc,就能重新讀取到a了。代碼如下:

#include <stdio.h>

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	fseek(pf, -3, SEEK_END); // 指向e
	putchar(fgetc(pf)); // 讀完e后指向f

	fseek(pf, -4, SEEK_CUR); // 指向b
	putchar(fgetc(pf)); // 讀完b后指向c

	printf("\n%ld\n", ftell(pf));

	rewind(pf);
	printf("%ld\n", ftell(pf));
	putchar(fgetc(pf)); // a

	fclose(pf);
	pf = NULL;

	return 0;
}

輸出結(jié)果:

C語(yǔ)言如何實(shí)現(xiàn)隨機(jī)讀寫(xiě)文件

當(dāng)然,把上述代碼中的rewind(pf);換成fseek(pf, 0, SEEK_SET);的效果是一樣的。

感謝各位的閱讀,以上就是“C語(yǔ)言如何實(shí)現(xiàn)隨機(jī)讀寫(xiě)文件”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)C語(yǔ)言如何實(shí)現(xiàn)隨機(jī)讀寫(xiě)文件這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI