文件處理函數如何使用?用法舉例,C與MFC

C語言,有時候真不得不佩它,照理說,文件處理函數是沒有什麼好講的,但對於很多C入門的人來說,似乎也是值得靜心品味一番的。

C中的文件處理函數並不很多,而常用的,似乎更少。

函數不難,但並不代表文件處理也不難。似乎又要有點跑題了,我總是喜歡跑題。上幾天做夢,夢到我掉到月球上去啦……

對文件的操作,無非就是打開、讀寫、調整讀寫偏移指針以及關閉,似乎麼什可說的,也許事實也的確如此。還是讓我們來看一段經典代碼吧,這代碼可是我自己寫的。

FILE* fp = fopen("test.txt", "r"); assert(fp); //打開文件,給一個斷言,這是一種好習慣

fseek(fp, 0, SEEK_END); //把偏移指針指向文件的結尾

unsigned int nlen = ftell(fp); //返回當前的偏移指針,也就是返回剛剛設定的文尾位置

fseek(fp, 0, SEEK_SET); //把讀寫偏移指針指向文件的開頭

char* const _psz = (char*)malloc(nlen + 1); //申請一段堆內存,這裏的_psz爲什麼要被const修飾呢?

unsigned int size = fread(_psz, sizeof(char), nlen, fp); //讀出文件的內容

_psz[size] = '\0'; //注意,必須要在字符串的結尾處添加結束標誌,否則,哼哼!

fclose(fp); //關閉文件

…… //東搞搞,西搞搞

free(_psz); //歸還堆內存

實在是太簡單了是吧?是的,我正這樣認爲呢。

在讀文件的時候,有點東西還是要說說的。因爲我們都聽說過,文件有兩種格式,一種是文本,一種是二進制。文本文件,當然,我們不想說什麼了,但二進制文件的讀寫,卻值得一提。二進制的文件這樣打開:

FILE* fp = fopen("test.exe", "rb"); assert(fp);

當然,可執行文件只不過是二進制文件的一個代表,在使用讀寫標誌的時候,我們需要"b"後綴,表明打開的是二進制的文件。其實,這不是關鍵,而正真關鍵的部分是對文件的讀寫,這份代碼有點冗餘,但不寫又怕給人鬧出強迫症。

fseek(fp, 0, SEEK_END); //獲取文件大小

size_t nlen = ftell(fp);

fseek(fp, 0, SEEK_SET);

unsigned char* const _psz = (unsigned char*)malloc(nlen + 1); //顯然,申請的內存應該是BYTE格式

fread(_psz, sizeof(unsigned char), nlen, fp); //由於是二進制的文件,我們不必再對內存做處理

fclose(fp);

通常,這種用法不常見,而更多的對二進制文件的讀寫,是出現在socket上。比如,我們要從網上更新一個可執行文件,那麼必須使用二進制的打開標誌,否則,你得到的只不過是一串小的可憐的碎片。最簡單的從網上下載文件,我們可以使用MFC的CInternetSession封裝類,簡單的用法如下:

CString strUrl = "http://hi.baidu.com/idealsoft/tools/test.exe"; //看好這個200K的exe文件

CInternetSession sess; //我建議大家對象全部用小寫,感覺很實在,小而強大嘛!

CStdioFile* pFile = sess.OpenURL(strUrl); ASSERT(pFile);

我們照例還是獲得pFile的大小,假如說是nlen,之所以我沒有使用函數來獲得,其實有我的苦衷,如果讀者有興趣的話,可以看MFC分類下的文章《CFile如何使用,用法舉例》,反正,不管如何,假如我們現在已經獲得這個網絡文件的大小了,下面立即讀取。

char* const _psz = new char[nlen + 1]; ASSERT(_psz);

unsigned int size = pFile->Read(_psz, nlen);

…… //好,現在文件已經獲取了,幹一些自己想幹的事情

什麼都沒有幹成!

開始查找原因,但什麼都沒有找到!

開始懷疑網絡文件有問題!

開始懷疑MFC有問題!

開始懷疑VC有問題!

開始懷疑自己有問題!

的確有問題,問題在哪?我們先看看OpenURL的聲明吧,源碼始終是我們唯一可以依賴的!

CStdioFile* OpenURL(LPCTSTR pstrURL, DWORD dwContext = 1, DWORD dwFlags = INTERNET_FLAG_TRANSFER_ASCII, LPCTSTR pstrHeaders = NULL, DWORD dwHeadersLength = 0);

我們之前已經說過了,對於二進制文件的讀取,一定要用二進制標誌,CInternetSession也同樣不能例外。

CStdioFile* pFile = pSession->OpenURL(pczUrl, 1, INTERNET_FLAG_TRANSFER_BINARY);

這纔是正確的寫法,而在OpenURL這個函數的聲明中,pstrURL以後的參數都被賦予了默認值。再看dwFlags這個標誌位,原來它默認的是ASCII碼,也就是文本文件,可是我們要下載的,那是.exe文件,也就是二進制文件,所以好像搞錯了,而對於這個函數的第二個參數dwContext,到底是什麼意思?這不用你管,說實話,我也不太清楚,所以你想知道的,也是我想知道的,既然微軟已經把它填了一個解釋的連自己舌頭都要繞斷的默認值,那麼我們也就隨大溜吧,不過我這裏可以先偷偷的告訴你,它的英文解釋是:An application-defined value passed with the returned handle in callback,也就是:與回調中的返回句柄一同傳遞的一個應用程序定義的值!!!汗流浹背啊,不知所云,如果你想探個究竟,MSDN與源碼正在恭候你。

好,切入主題。

這樣一來,文件可以順利下載了,一切都很令你滿意,你開始有點得意的埋怨你剛剛的草率與魯莽,因爲一切都很正常。

這樣的結果,已經能夠令你滿意,你現在要做的是:

…… //東搞一下,西搞一下

delete[] _psz; //釋放堆內存

這樣,大功告成了,你準備接受老闆的讚賞,但得到的卻是兩個耳光!!

你憤恨,不滿,準備離開這裏。

真的大功告成了嗎?其實是大失告敗,現在,你一定會睜大眼睛,等待下文吧,對不起,我不是一個隨便的人,雖然隨便起來我不是人。

好,請您在《CFile如何使用,用法舉例》中尋找答案。     

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章