VC++讀寫文件


1讀寫文件    1

1.1 API    1

1.2 低級IO    1

1.2.1 文件序號    1

1.2.2 文本文件與二進制文件    1

1.3 IO    2

1.4 Unicode    3

1.5 IO、低級IOAPI之間的關系    3

1.6 隨機讀寫    4

1.7 C++IO    4

1.8 MFC    4

1.8.1 CFile    4

1.8.2 CStdioFile    4

1.8.3 CArchive    4

1.9 總結    5

 

1讀寫文件

1.1 API

使用VC++讀寫文件,最直接、最高效的方法就是使用 Windows API,如:使用 CreateFile 打開文件,使用 WriteFile 寫文件,使用 ReadFile 讀文件……Windows 平台下,所有對文件的讀寫操作,最終都會調用這些 API 函數。使用 API 的效率最高,對文件讀寫的控制最強,缺點就是比較復雜,而且代碼沒有可移植性。

1.2 低級IO

為了方便移植 UNIX C代碼,VC++C運行時庫實現了一套低級IO函數,如:_open_write_read……

1.2.1 文件序號

_open返回的是一個整數,MSDN上稱其為文件句柄(file handle),這與CreateFile返回的文件句柄容易混淆。為此,本文稱_open返回的為文件序號。

VC++中,系統預先打開了三個文件,其文件序號如下表所示

文件序號

stdin 

0 

標准輸入設備,一般就是鍵盤

stdout 

1 

標准輸出設備,一般就是控制台

stderr 

2 

標准錯誤輸出設備,一般就是控制台

也就是說,無需調用_open,可以直接調用_write(1,"abc",3);往控制台輸出abc三個字符。

1.2.2 文本文件與二進制文件

讀寫二進制文件時,不會做任何處理,數據保持原樣。寫文本文件時,VC++會將換行符(即\n0AH)替換為回車(即\r0DH)和換行符;讀文本文件時,VC++會將\r\n替換為\n,並且在讀取到1AH時,認為文件結束。

_open函數里可以指定文件模式,

如:_open("c:\\1.txt",_O_RDONLY | _O_TEXT);     //文本模式

如:_open("c:\\1.txt",_O_RDONLY | _O_BINARY);     //二進制模式

如果_open函數里未指定 _O_TEXT _O_BINARY,則以全局變量_fmode為准,如下面的代碼將以文本模式打開文件。

_fmode = _O_TEXT;

_open("c:\\1.txt",_O_RDONLY);

假定c:\1.txt的內容如下:

1 

2 

3 

\r 

\n 

4 

5 

6 

\r 

\n 

執行如下代碼:

int    n = _open("c:\\1.txt",_O_RDONLY | _O_BINARY);

char    str[128];

_read(n,str,128);

_close(n);

str的內容將是"123\r\n456\r\n"。將_O_BINARY替換為_O_TEXT,則str的內容將變為"123\n456\n"。可見\r\n如期的被替換為\n。不過,需要注意的是:將\r\n替換為\n是在第二個參數內進行的,如:將_read(n,str,128);替換為下面兩行代碼:

_read(n,str,4);    //讀取到"123\r"

_read(n,str,4);    //讀取到"\n456"

這個時候,\r\n就不會被替換為\n。這點要特別注意。

1.3 IO

IO函數有:fopenfwritefread……它與低級IO最大的區別在於:低級IO無緩沖區,而流IO有緩沖區。如:同樣的寫文件,_write 會直接調用 WriteFile,而 fwrite 會將數據寫入緩沖區,達到一定數量后,再調用 WriteFile 將緩沖區內的數據寫入文件。顯然,流IO將大大減少調用 API 函數的次數,因此理論上其效率會比較高。

使用setvbuf函數,可以對緩沖區的大小、行為進行設置。

VC++里,流IO由低級IO實現。即:fopen會調用_openfwrite會調用_writefgets會調用_read函數……

IO最重大的意義在於:它是符合ANSI C 標准的一套函數,可移植性最高。

1.4 Unicode

WindowsAPI函數一般會分為兩個版本,即處理ANSI字符串的窄字符版本,和處理Unicode字符串的寬字符版本。低級IO和流IO也有類似的寬字符版本函數,如:_wopen_wfopen……

使用寬字符版本的IO函數之前,一定要調用setlocale(LC_ALL,""),設置 C 函數的代碼頁為系統默認的代碼頁,否則就有可能會出現亂碼。

1.5 IO、低級IOAPI之間的關系

三者的關系如下圖所示:流IO由低級IO實現,而低級IOAPI實現。

函數_fileno可根據流IOFILE*獲得低級IO的文件序號;

函數_get_osfhandle可根據低級IO的文件序號獲得API的文件句柄;

函數_open_osfhandle可根據API的文件句柄獲得低級IO的文件序號;

函數_fdopen可根據低級IO的文件序號獲得流IOFILE*

1.6 隨機讀寫

隨機讀寫是對文件讀寫的一種方式,具體表現為:

1、讀或寫時,會移動文件指針;

2、讀、寫操作交叉進行,如:讀了幾次后又寫幾次。

如果使用低級IO進行隨機讀寫,讀寫函數的處理是比較簡單的。反之,對於有緩沖區的流IO而言,隨機讀寫反而可能會降低文件的讀寫效率。因為以上兩個操作,將頻繁的清空緩沖區、移動文件指針。可以說,在隨機讀寫文件上,流IO並不比低級IO有優勢。

1.7 C++IO

C++STL中,可以使用 fstreamifstreamofstream……對文件進行讀寫。它的內部使用了流IO

1.8 MFC

1.8.1 CFile

CFile是低級IOC++實現。它直接調用 API,主要用於讀寫二進制文件。

1.8.2 CStdioFile

CStdioFile用於讀寫文本文件,具體的就是讀寫一行行的文本。它內部調用了流IO。當以 Unicode 編譯程序時,CStdioFile 將調用 Unicode 版本的流IO函數,此時一定要首先調用 setlocale(LC_ALL,"")。還需要說明的一點是:從 EVC3.0 VC2008CStdioFile 都是無法正常運行在 Windows CE 平台上的。

1.8.3 CArchive

CArchive 主要用於串行化,它可以與 CFile CMemFile 關聯,然后通過<<>>方便的實現變量的串行化和反串行化。

CArchive CFile 關聯,串行化時變量將保存至文件。

CArchive CMemFile 關聯,串行化時變量將保存至內存。

CArchive CSocketFile關聯,串行化時變量將通過套接字傳輸到網絡。

1.9 總結

如果使用C語言,可以選擇使用API、低級IO、流IO。如果代碼要移植到其它平台,建議使用流IO。如果使用C++語言,上述方法均可使用。

讀寫二進制文件相對比較容易,比較復雜的是讀寫文本文件。復雜在兩個方面:

1、各個操作系統定義的行結束符不盡相同,如:Linux定義\r為行結束符,Mac定義\n為行結束符,Windows定義\r\n為行結束符。而且,還需要考慮各個操作系統之間的文件讀寫,如:Linux生成的文本文件在Windows下讀取……

2、必須考慮多種編碼。如:Windows平台下,文本文件分為四種格式:ANSIUTF16LEUTF16BEUTF-8VC++6.0只支持讀寫ANSI編碼的文本文件。自VC++2005開始,fopen增加了對UTF16LEUTF-8這兩種編碼的支持,不過這種支持不適用於 Windows CE 平台。

上述兩個問題,最好的解決辦法就是自行編寫一個處理文本文件的C++類。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM