ZWeily的小品文(一)MFC中的檔案讀寫問題 (轉)

worldblog發表於2007-12-14
ZWeily的小品文(一)MFC中的檔案讀寫問題 (轉)[@more@]

“終於搞定了”,只聽見Weily在工作臺前自言自語。

 :namespace prefix = o ns = "urn:schemas--com::office" />

“忙了幾天,終於把主要的都去掉了,該休息一會兒了。”於是Weily拿起桌上的那隻印有楊威利頭像的杯子,準備去泡點喝的。

 

“叮!”Weily在經過Pisces的座位的時候被這一個突如其來的響聲嚇了一跳,差點把手上的杯子扔了出去,還好,只是差點……

 

“不是告訴過你嘛,工作的時候別把音響開這麼響,你要知道,剛才你差點把我的寶貝杯子給砸了,還好我不是被嚇大的,否則,這個杯子你可賠不起啊!”

 

“……對不起啦!下次不敢了……”Pisces做著鬼臉給Weily賠不是。

 

“你還想要下次啊?!”

 

“不了”Pisces趕忙把音響給關了,“對了,Weily,你能不能過來幫我一下啊,我這裡……嗯……有點問題搞不定了……”

 

“啊?又有什麼問題啊?”

 

“這個……那個……”Pisces似乎說不清楚,“還是你過來看看吧。我幫你去弄喝的”

 

還沒等Weily反應過來,Pisces就一把搶過了Weily的那個寶貝杯子,往飲水機走了過去。

 

“小心!小心!那是我的杯子……”Weily搖搖頭,就在Pisces的位子上坐了下來,有點迷茫的看著螢幕。

 

1分18秒後……

 

“問題找到了嗎?”Pisces又突然出現在Weily的背後,手上端著Weily的杯子,“嗯,先喝點東西吧。”

 

Weily心神未定的接下Pisces手中的杯子,嘆了口氣,自言自語:“怪不得我感覺越來越有精神衰弱的徵兆了。”

 

“嗯,問題我大致知道了,你過來看……”Weily說完,端起杯子喝了一口。

 

“噗……………………”只見Weily把剛喝的一小口東西全都噴了出來,“你……你……你給我泡的是什麼啊?”

 

“雀巢1+2咖啡啊?”Pisces一臉無辜的答道,“怎麼了啊?”

 

“哎……看來你還是不瞭解我啊!我剛才想去泡的是紅茶,還準備加點蜂蜜。你應該知道的,我平時不喝咖啡的啊,就算喝咖啡,也只喝清咔,不加任何東西的呀!你怎麼給我泡了這種咖啡,真是的,糟踏了我的杯子啊……”Weily連珠炮似的抱怨道。

 

“嗯,是我不好,我習慣喝這種1+2咖啡了,忘了這次是給你喝的,是在抱歉啊。我給你去重泡一杯吧。”Pisces用非常誠懇地承認錯誤。

 

“算了,我也暫時不喝了,等一下我還是自己去泡吧,省得你再給我泡出什麼亂七八糟的東西。”Weily也算是習慣了Pisces的這種風格,“好了,先說說你自己遇到的問題吧。”

 

“大致是這樣的:我這個小是從中一個個字元讀入資料,然後處理後放到一個緩衝區裡,最後再輸出到一個新的檔案中。我剛開始學MFC,我用CFile類的Read()逐個讀入字元,處理後放到一個CString類的裡,最後用的是CStdioFile類的WriteString()函式將緩衝區的內容輸出到檔案中。”Pisces邊指著螢幕上的程式碼,邊說道。

 

“那有什麼問題呢?”Weily故意問道。

 

“嗯,我用UltraEdit來檢視我輸出後的結果檔案,可是開啟的時候老是有一個提示:‘Do you want to convert to Dformat?’”

 

“呵呵,問題在哪裡知道嗎?在於你沒有好好的理解MFC裡面的那個CStdioFile類的WriteString()函式的注意事項。”Weily邊說邊開啟了桌面上的MSDN,在中輸入了‘CStdioFile’,然後就標出了下面這段:

“Text mode provs special processing for carriage return–linefeed pairs. When you write a newline character (0x0A) to a text-mode CStdioFile , the byte pair (0x0D, 0x0A) is sent to the file. When you read, the byte pair (0x0A, 0x0D) is translated to a single 0x0A byte.”

“這段東西你總看得懂吧?那你說說看主要講了些什麼?”

 

“大致就是CStdioFile在寫出換行符(0x0A)的時候,會將它轉換成(0x0D, 0x0A)這樣一個字元對,然後輸出。而在讀入的時候,會將字元對(0x0D, 0x0A)轉換成單個換行符(0x0A)。沒說錯吧?”

 

“對,沒說錯,那你知道0x0D和0x0A的區別嗎?”

 

“我只知道一個是換行,一個是回車,哪個是哪個我就……嗯……搞不清除了”

 

“那你平時寫程式的時候寫的’n’是哪個?”

 

“……”

 

看著Pisces一臉迷茫的樣子,Weily臉上閃過一絲得意,不過那只是一個瞬間,極短極短的一個瞬間,大概比0.05秒還要短吧。不過,這個瞬間還是被Pisces看到了,只是現在有求於人,就只能忍著了。

 

“我們通常用的’n’是換行符,’r’是回車符。回車和換行的區別你應該知道,我就不說的。它們相對應的ASCII碼分別是:0x0A和0x0D。”

 

“嗯,懂了。那和我這個程式有什麼關係嗎?”Pisces有點似懂非懂。

 

“哎……你是用什麼方式讀入檔案的?”Weily耐下性子問。

 

“一個個字元,逐個讀入。”

 

“那你怎麼輸出到檔案的?”

 

“用CStdioFile的WriteString()函式一次寫出的。”

 

“對!問題就出在這裡。你先用UltraEdit開啟你的原檔案和你生成的檔案,用二進位制方式察看,注意看檔案中每行換行的地方,你看到了什麼?”

 

Pisces按照Weily說得去做了,然後似乎有了什麼發現,“原檔案換行的地方都是2個字元(0x0D, 0x0A),而我生成的檔案變成了(0x0D, 0x0D, 0x0A)三個字元。這是怎麼回事啊?”

 

“剛才我讓你看得MSDN中的那段呢?你倒是將這些都聯絡起來,好好想想啊!”看來Weily有點耐不住性子了,有點受不了了。

 

“噢!我知道了。我逐個讀入字元,那麼我會先督導’r’,然後這個字元我就直接寫到CString裡了,然後再讀到’n’,也寫到CString裡了。可是在CStdioFile輸出的時候,他會將後面那個’n’轉換成’r’、’n’字元對,但是前面還有一個’r’還是存在的,這樣就多出一個回車符了。”Pisces似乎有所領悟了。

 

“嗯,總算還不是塊朽木,那麼知道怎麼解決了嗎?”

 

“嗯,我就在讀入的時候加個判斷,如果是’r’,就表示換行了,那麼我就將這個字元跳過,讀入下一個’n’,寫到CString裡。”

 

“好了,這個問題基本上解決了。但是你這個程式還有問題知道嗎?”Weily用那種故意裝成平靜的語氣說道,“你這個程式一旦讀入的檔案比較大的話,就會極差,給的感覺就像當機,如果使用者的機器不夠快的話,就會真的變成程式未響應!”

 

“啊?這麼嚴重啊?那問題出在哪裡呢?”Pisces一臉狐疑,似乎不相信Weily所說的。

 

“呵呵,你不信啊?那你自己試試看啊!”Weily用一種十分肯定的語氣給了Pisces當頭一棒。

 

“嗯,算了,我不試了,我信你,那你告訴我問題所在吧?”Pisces的語氣有點顫抖,也有點不服氣,不過沒辦法,被別人抓住了把柄,也就只有聽話的份了。

 

“好吧,告訴你吧。你應該聽說過MFC的效率低下的問題吧?你這個程式就能很好的證明這一點。你是處理完整個檔案再一次性將檔案寫出。可是CStdioFile的WriteString()函式的效率很低,一旦作為引數的CString比較大的時候,就會明顯的反應出這個問題。”

 

“那我該怎麼辦呢?”

 

“這還不簡單,反正你加上了判斷換行的語句,那就在處理完一行後就寫出到檔案啊!”

 

“噢~~~,原來如此!嗯,Weily,這次多謝了,以後還請你多多關照……”

 

還沒等Pisces說完,Weily就拿著他的寶貝杯子走了,嘴裡嘟噥著:“還得洗杯子,重泡一杯紅茶,好好休息一下……”

 

可是,Weily還沒走到洗杯子的地方的時候,下班的鈴聲響了。

 

“本來想忙完了,可以在下班前休息一下的,結果……”Weily長長地嘆了一口氣,“哎……”

 

而Pisces搞定了程式,正在收拾東西,準備回家……


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-993494/,如需轉載,請註明出處,否則將追究法律責任。

相關文章