C語(yǔ)言中文件常見(jiàn)操作的示例詳解
FILE為C語(yǔ)言提供的文件類(lèi)型,它是一個(gè)結(jié)構(gòu)體類(lèi)型,用于存放文件的相關(guān)信息。文件打開(kāi)成功時(shí),對(duì)它作了內(nèi)存分配和初始化。
每當(dāng)打開(kāi)一個(gè)文件的時(shí)候,系統(tǒng)會(huì)根據(jù)文件的情況自動(dòng)創(chuàng)建一個(gè)FILE結(jié)構(gòu)的變量,并填充其中的信息,使用者不必關(guān)心細(xì)節(jié)。
一般都是通過(guò)一個(gè)FILE的指針來(lái)維護(hù)這個(gè)FILE結(jié)構(gòu)的變量,這樣使用起來(lái)更加方便。
文件打開(kāi)和關(guān)閉
C語(yǔ)言的安全文件打開(kāi)函數(shù)為_(kāi)wfopen_s和_fopen_s。
errno_t _wfopen_s( FILE** pFile, const wchar_t *filename, const wchar_t *mode );
參數(shù)pFile
指向文件指針的指針,該文件指針將接收指向打開(kāi)文件的指針。
參數(shù)filename
表示要打開(kāi)的文件名
參數(shù)mode
表示訪問(wèn)方式,該參數(shù)可設(shè)置的值如下表。
模式 | 含義 |
---|---|
"r" | 打開(kāi)以供閱讀。如果文件不存在或找不到,則fopen_s調(diào)用將失敗 |
"w" | 打開(kāi)一個(gè)空文件進(jìn)行寫(xiě)入。如果給定文件存在,則其內(nèi)容將被銷(xiāo)毀 |
"a" | 在新數(shù)據(jù)寫(xiě)入文件之前,在文件末尾打開(kāi)以寫(xiě)入(追加),而不刪除文件結(jié)束 (EOF) 標(biāo)記。如果文件不存在,則創(chuàng)建該文件 |
"r+" | 可打開(kāi)讀取和寫(xiě)入。該文件必須存在 |
"w+" | 打開(kāi)一個(gè)空文件進(jìn)行讀取和寫(xiě)入。如果該文件存在,則其內(nèi)容將被銷(xiāo)毀 |
"a+" | 打開(kāi)以供閱讀和追加。追加操作包括在將新數(shù)據(jù)寫(xiě)入文件之前刪除 EOF 標(biāo)記。寫(xiě)入完成后,不會(huì)還原 EOF 標(biāo)記。如果文件不存在,則創(chuàng)建該文件 |
除了上述模式外,還可以包含以下字符,以指定換行符的轉(zhuǎn)換模式:
模式修改器 | 翻譯模式 |
---|---|
t | 以文本(翻譯)模式打開(kāi)。 |
b | 以二進(jìn)制(未翻譯)模式打開(kāi);禁止顯示涉及回車(chē)符和換行符的轉(zhuǎn)換。 |
返回值
如果成功,則為零;失敗時(shí)的錯(cuò)誤代碼
使用Close函數(shù)文件關(guān)閉。
文件寫(xiě)入
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
參數(shù)buffer
表示存儲(chǔ)讀取數(shù)據(jù)的緩沖區(qū)
參數(shù)size
表示要寫(xiě)入數(shù)據(jù)的一個(gè)字符的大?。ㄒ宰止?jié)為單位)
參數(shù)count
表示要寫(xiě)入數(shù)據(jù)的字符數(shù)
參數(shù)stream
表示指向文件結(jié)構(gòu)體的指針
返回值
fwrite返回函數(shù)寫(xiě)入的完整項(xiàng)數(shù),如果發(fā)生錯(cuò)誤,該數(shù)可能小于count。
文件讀取
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
參數(shù)buffer
表示存儲(chǔ)讀取數(shù)據(jù)的緩沖區(qū)
參數(shù)size
表示要讀取數(shù)據(jù)的一個(gè)字符的大?。ㄒ宰止?jié)為單位)
參數(shù)count
表示要讀取數(shù)據(jù)的字符數(shù)
參數(shù)stream
表示指向文件結(jié)構(gòu)體的指針
返回值
fread返回函數(shù)讀取的完整項(xiàng)目數(shù),如果發(fā)生錯(cuò)誤,或者在達(dá)到COUNT 之前遇到文件末尾,則可能小于Count。
fseek函數(shù)
可以通過(guò)fseek函數(shù)設(shè)置文件指針的位置。通過(guò)該方法可以計(jì)算出文件的大小
int fseek( FILE *stream, long offset, int origin );
參數(shù)stream
表示指向文件結(jié)構(gòu)體的指針
參數(shù)offset
表示指針的偏移量
參數(shù)origin
表示指針?biāo)幬恢?,其可以設(shè)置的如下的取值
取值 | 意義 |
---|---|
SEEK_CUR | 文件指針的當(dāng)前位置 |
SEEK_END | 文件結(jié)束 |
SEEK_SET | 文件的開(kāi)頭 |
ftell函數(shù)
ftell函數(shù)可以獲取文件指針的當(dāng)前位置。通過(guò)fseek結(jié)合ftell兩個(gè)函數(shù)可以計(jì)算出文件的大小
long ftell( FILE *stream );
Demo示例
寫(xiě)數(shù)據(jù):
void CMyFileCFileView::OnFileWrite() { FILE* pFile = NULL; //打開(kāi)文件 errno_t err = _wfopen_s(&pFile, _T("1.txt"), _T("w")); if (err != 0) { TRACE("Open File failed errorcode :%d", GetLastError()); return; } fwrite(L"Hello World", 2, wcslen(L"Hello World")+1, pFile); fclose(pFile); }
讀數(shù)據(jù):
void CMyFileCFileView::OnFileRead() { FILE* pFile = NULL; errno_t err = _wfopen_s(&pFile, _T("1.txt"), _T("r")); if (err != 0) { TRACE("Open File failed errorcode :%d", GetLastError()); return; } fseek(pFile, 0, SEEK_END);//文件指針定位,偏移到結(jié)尾 int len = ftell(pFile);//得到文件指針的當(dāng)前位置 = 每個(gè)字符大小×字符長(zhǎng)度 WCHAR* pBuf = new WCHAR[len]; fseek(pFile, 0, SEEK_SET);//文件指針回到文件起始位置 pBuf[len] = 0; fread(pBuf, 2, len, pFile); MessageBox(pBuf); fclose(pFile); }
解決讀取亂碼
使用C語(yǔ)言進(jìn)行文件操作時(shí)如果稍微不注意很容易讀出亂碼。一般出現(xiàn)這種亂碼有兩種原因,一種時(shí)寫(xiě)入的數(shù)據(jù)沒(méi)有寫(xiě)入結(jié)束符,另一種是讀取數(shù)據(jù)時(shí),讀取數(shù)據(jù)的個(gè)數(shù)設(shè)置出錯(cuò)。
例如下面這種寫(xiě)入數(shù)據(jù)和讀取數(shù)據(jù)的代碼,運(yùn)行出來(lái)就會(huì)出現(xiàn)亂碼。
//寫(xiě)數(shù)據(jù) fwrite(L"Hello World", 2, wcslen(L"Hello World"), pFile); //讀數(shù)據(jù) //pFile此時(shí)移動(dòng)到了文件末尾 int len = ftell(pFile);//得到文件指針的當(dāng)前位置 = 每個(gè)字符大小×字符長(zhǎng)度 WCHAR* pBuf = new WCHAR[len]; fseek(pFile, 0, SEEK_SET);//文件指針回到文件起始位置 fread(pBuf, 2, len, pFile);
使用ftell獲取的文件指針到的位置為 一個(gè)字符大小 ×字符長(zhǎng)度。 雖然"Hello World"有11個(gè)字符,但是WCHAR類(lèi)型,所以ftell返回的值為22。在之后使用fread讀取數(shù)據(jù)時(shí)讀到了len×2=44字節(jié)的內(nèi)容,而寫(xiě)入的數(shù)據(jù)才22字節(jié),因此會(huì)出現(xiàn)亂碼。
解決方法:
方法一:給存儲(chǔ)的數(shù)據(jù)結(jié)尾加上結(jié)束符'\0"
在寫(xiě)數(shù)據(jù)時(shí):
fwrite(L"Hello World", 2, wcslen(L"Hello World")+1, pFile);
寫(xiě)入的實(shí)際長(zhǎng)度+1,這樣寫(xiě)入的數(shù)據(jù)后面會(huì)增加一個(gè)'\0'結(jié)束符。
fread在達(dá)到COUNT 之前遇到文件末尾也會(huì)停止。這樣在緩沖緩沖數(shù)組就可以讀到實(shí)際數(shù)據(jù)和一個(gè)結(jié)束符。打印時(shí)就能正常打印出。
//寫(xiě)數(shù)據(jù) fwrite(L"Hello World", 2, wcslen(L"Hello World")+1, pFile); //讀數(shù)據(jù) //pFile此時(shí)移動(dòng)到了文件末尾 int len = ftell(pFile);//得到文件指針的當(dāng)前位置 = 每個(gè)字符大小×字符長(zhǎng)度 WCHAR* pBuf = new WCHAR[len]; fseek(pFile, 0, SEEK_SET);//文件指針回到文件起始位置 fread(pBuf, 2, len, pFile);
方法二:限制讀取的大小
因?yàn)閘en得到的是一個(gè)字符的大小×字符數(shù),如果把len/sizeof(WCHAR),就可以獲得實(shí)際的字符數(shù)。在讀取數(shù)據(jù)時(shí)使用這個(gè)實(shí)際的長(zhǎng)度作為讀取數(shù),之后將緩沖數(shù)組len的位置賦值為'\0'。就可以讀取到實(shí)際數(shù)據(jù)
//寫(xiě)數(shù)據(jù) fwrite(L"Hello World", 2, wcslen(L"Hello World"), pFile); //讀數(shù)據(jù) //pFile此時(shí)移動(dòng)到了文件末尾 int len = ftell(pFile);//得到文件指針的當(dāng)前位置 = 每個(gè)字符大小×字符長(zhǎng)度 WCHAR* pBuf = new WCHAR[len]; fseek(pFile, 0, SEEK_SET);//文件指針回到文件起始位置 fread(pBuf, 2, len/2, pFile); pBuf[len/2] = 0;
到此這篇關(guān)于C語(yǔ)言中文件常見(jiàn)操作的示例詳解的文章就介紹到這了,更多相關(guān)C語(yǔ)言文件操作內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談C++/C關(guān)于#define的那些奇奇怪怪的用法
本文主要介紹了C++/C關(guān)于#define的那些奇奇怪怪的用法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07Visual Studio調(diào)試C/C++教程指南
VisualStudio是微軟開(kāi)發(fā)的一款集成開(kāi)發(fā)環(huán)境軟件,本文主要介紹了Visual Studio調(diào)試C/C++教程指南,熟悉地掌握基于VS的C/C++調(diào)試技術(shù),可以大幅提升調(diào)試性能,感興趣的可以了解一下2024-06-06C/C++雜記 虛函數(shù)的實(shí)現(xiàn)的基本原理(圖文)
這篇文章主要介紹了C/C++雜記 虛函數(shù)的實(shí)現(xiàn)的基本原理(圖文),需要的朋友可以參考下2016-06-06基于OpenCV實(shí)現(xiàn)的人臉簽到系統(tǒng)源代碼
本文從實(shí)際背景和需求出發(fā),采用人臉識(shí)別簽到考勤改變了傳統(tǒng)人工檢驗(yàn)的做法,極大提高了組織效率和辦事能力,這篇文章主要給大家介紹了關(guān)于如何基于OpenCV實(shí)現(xiàn)的人臉簽到系統(tǒng)的相關(guān)資料,需要的朋友可以參考下2024-04-04C 標(biāo)準(zhǔn)I/O庫(kù)的粗略實(shí)現(xiàn)教程
下面小編就為大家分享一篇C 標(biāo)準(zhǔn)I/O庫(kù)的粗略實(shí)現(xiàn)教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12Qt實(shí)現(xiàn)定時(shí)器的兩種方法分享
這篇文章主要為大家詳細(xì)介紹了Qt中實(shí)現(xiàn)定時(shí)器的兩種不同方法,文中的示例代碼講解詳細(xì),對(duì)我們了解Qt有一定的幫助,感興趣的可以跟隨小編一起學(xué)習(xí)一下2022-11-11C語(yǔ)言實(shí)現(xiàn)txt數(shù)據(jù)讀入內(nèi)存/CPU緩存實(shí)例詳解
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)txt數(shù)據(jù)讀入內(nèi)存/CPU緩存實(shí)例詳解的相關(guān)資料,這里對(duì)實(shí)現(xiàn)該函數(shù)進(jìn)行了代碼實(shí)現(xiàn),需要的朋友可以參考下2017-01-01