ZWeily的小品文(一)MFC中的文件读写问题

类别:VC语言 点击:0 评论:0 推荐:

“终于搞定了”,只听见Weily在工作台前自言自语。

 

“忙了几天,终于把主要的bug都去掉了,该休息一会儿了。”于是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 DOS format?’”

 

“呵呵,问题在哪里知道吗?在于你没有好好的理解MFC里面的那个CStdioFile类的WriteString()函数的注意事项。”Weily边说边打开了桌面上的MSDN,在索引中输入了‘CStdioFile’,然后就标出了下面这段:

“Text mode provides special processing for carriage return–linefeed pairs. When you write a newline character (0x0A) to a text-mode CStdioFile object, 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搞定了程序,正在收拾东西,准备回家……

本文地址:http://com.8s8s.com/it/it1961.htm