fread读取数据效率和Rich Edit字符串处理问题 本帖最后由 LENOVO_ 于 2010-02-19 22:39:30 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 你这种读文件的方式,得确很慢,每次都是读取16个字节,这样I/O太繁忙了,最好是一次多读取一些在内存缓存,然后再处理,一般读取时就以Windows页面大小4K大小读取最佳。另外你还得考虑用滑动窗口的方式分段读取,文件小的时候没事,一旦文件大了,你的这个程序打开一个文件超级慢。象你这样上1M的文件处理起来都会很慢。至于自动对应的问题倒没事,因为因可以知道两个框中的具体字符串位置,然后用SetSel来选中就行了。 我认为效率低并不是一次读取数据太少造成的,因为这些常用的文件读写函数本身已经提供了4k的缓冲区。hexdata+=pBuf;这样的语句用起来很简单吧,问题就在这里。每附加一次数据,CString都得分配一个更大块的内存,把旧的和新的数据copy进去,然后把旧的内存区释放的。这些都是费时的操作。用Preallocate(int n)预先分配一大块内存,速度就上去了。 回 1 楼的,我试了一下,读 1.10MB的WMA音乐文件,刚开始会卡住一会,象UltraEdit这种软件可以一下子打开,不过往下刷的时候会出现闪烁,过一会就好了。主要是一次读多了,不好插入"\r\n",你说的滑动窗口和分段读取我不知道怎么写代码,没写过。回 2 楼,确实慢。回 3 楼,确实你说的对,每次 += 都要复制一遍旧串。Preallocate(int n) 没用过,网上查了一下,也说得乱七八糟的。谢谢几位的回复,我还需要等待,等待更具体一点的指点。 开个大的buf去读吧,效率的事情由系统去做。 preallocate是CString的一个成员函数,用于预先保存一定的内存,这样在连接字符串的时候在内存未用完之前,只要把新串加到后面就行了。拿你的代码来说吧: int readnumber=0; FILE* fpopen=NULL; CString hexdata; CString charactor;加到这里:hexdata.preallocate(40960); charactor.preallocate(40960);预分配的内存越大,速度会越快。 回 5 楼,谢谢。回 “宏景工作室”,采纳了你的意见后,发现快了好几倍。我首先获取文件的大小,然后计算出要分配多少内存空间。 CFileStatus filestatus; unsigned long int filesize=0; if( CFile::GetStatus(sourcefile.GetPathName(),filestatus) ) //获取文件大小 { filesize=filestatus.m_size; } hexdata.Preallocate(filesize*3 + (filesize/16)*2 + 16); charactor.Preallocate(filesize + (filesize/16)*2 + 16);用 GetTickCount()计算出从打开 1.10MB的文件到显示出数据到Rich Edit 是2328毫秒。原来没有先 Preallocate 的用了6331毫秒。确实被你说中了,谢谢指点。那个每次读多少字节就算了,暂且不管他了。现在来研究一下,怎么实现鼠标选择后,框住另外一边的效果。先谢谢你了,我再研究一下。 这个文本框的字符是一一对应的,这就好办了。主要是处理en_selchange事件,每当光标位置或选择的内容有变化时,就会出现这个事件。发生这个事件时,可以取得当前光标的位置或选择的起终位置。然后把字符框设置一下就行了. 其实你可以用createfile()来打开文件,它的最后一个参数是可以优化读取速度的 回 8 楼,我尝试了一下你说的 EN_CHANGE 事件,(你说的那个EN_SELCHANGE我没找到消息映射宏,汗!找了半天)。也用到了SetEventMask(GetEventMask() | ENM_CHANGE | ENM_SELCHANGE),都没用。无奈!只好响应ON_WM_MOUSEMOVE()ON_WM_LBUTTONDOWN()ON_WM_PAINT()void CMyDialog::OnMouseMove(UINT nFlags, CPoint point){ if(nFlags == MK_LBUTTON) { richedit1->GetSel(nStartChar,nEndChar); richedit2->SetSel(nStartChar/3,nEndChar/3); flag=0; Invalidate(); } CDialog::OnMouseMove(nFlags,point);}void CMyDialog::OnPaint(){ CHARFORMAT2 cfm; cfm.cbSize=sizeof(cfm); richedit2->GetSelectionCharFormat(cfm); cfm.dwEffects=0; if(flag == 0) { cfm.crTextColor=RGB(255,255,255); //蓝底白字 cfm.crBackColor=RGB(10,36,106); } else if(flag == 1) { cfm.crTextColor=RGB(0,0,0); //白底黑字 cfm.crBackColor=RGB(255,255,255); } cfm.dwMask=CFM_BACKCOLOR | CFM_COLOR; richedit2->SetSelectionCharFormat(cfm); CDialog::OnPaint(); }void CMyDialog::OnLButtonDown(UINT nFlags, CPoint point){ richedit2->SetSel(nStartChar/3,nEndChar/3); flag=1; Invalidate();}哎,每次都是必须把光标移动到 Rich Edit控件外才能重绘,还要按着左键。好像光标在空间范围里面就不响应消息。糟糕透了!都搞了 6 个小时了。真是麻烦。继续做一下,再做不出来就不搞了。 vs2008带的MFC中有selchanage不知道,不知道你用的是什么? preallocate,我也学习ing谢谢! 我想找开发相关的实习,简历怎样写才合适 请问下GridCtrl控件的列表行距怎么变大?谢谢 周末了,练习练习散分=.= 关于一服务器多客户端的数据接收问题(在线等待中) 如何将BOOL转成VARIANT_BOOL? 怎样编程使我的程序运行后桌面上只有一个图标?谢谢! 请教 在vb中双击toolbar时,总会弹出“自定义工具栏”,想截获这个双击消息,how to 在ACTIVEX中手工加载MDI文档该如何做 MFC如何创建类似于visual studio那样的停靠窗口请贴出代码 结构体变量的值 是一个变化的值 怎么处理 为什么说C盘空间小影响速度?
hexdata+=pBuf;这样的语句用起来很简单吧,问题就在这里。每附加一次数据,CString都得分配一个更大块的内存,把旧的和新的数据copy进去,然后把旧的内存区释放的。这些都是费时的操作。用Preallocate(int n)预先分配一大块内存,速度就上去了。
int readnumber=0;
FILE* fpopen=NULL;
CString hexdata;
CString charactor;
加到这里:hexdata.preallocate(40960);
charactor.preallocate(40960);
预分配的内存越大,速度会越快。
CFileStatus filestatus;
unsigned long int filesize=0;
if( CFile::GetStatus(sourcefile.GetPathName(),filestatus) ) //获取文件大小
{
filesize=filestatus.m_size;
} hexdata.Preallocate(filesize*3 + (filesize/16)*2 + 16);
charactor.Preallocate(filesize + (filesize/16)*2 + 16);用 GetTickCount()计算出从打开 1.10MB的文件到显示出数据到Rich Edit 是2328毫秒。原来没有先 Preallocate 的用了6331毫秒。确实被你说中了,谢谢指点。那个每次读多少字节就算了,暂且不管他了。现在来研究一下,怎么实现鼠标选择后,框住另外一边的效果。先谢谢你了,我再研究一下。
ON_WM_LBUTTONDOWN()
ON_WM_PAINT()
void CMyDialog::OnMouseMove(UINT nFlags, CPoint point)
{
if(nFlags == MK_LBUTTON)
{
richedit1->GetSel(nStartChar,nEndChar);
richedit2->SetSel(nStartChar/3,nEndChar/3);
flag=0;
Invalidate();
} CDialog::OnMouseMove(nFlags,point);
}void CMyDialog::OnPaint()
{
CHARFORMAT2 cfm;
cfm.cbSize=sizeof(cfm);
richedit2->GetSelectionCharFormat(cfm);
cfm.dwEffects=0;
if(flag == 0)
{
cfm.crTextColor=RGB(255,255,255); //蓝底白字
cfm.crBackColor=RGB(10,36,106);
}
else if(flag == 1)
{
cfm.crTextColor=RGB(0,0,0); //白底黑字
cfm.crBackColor=RGB(255,255,255);
}
cfm.dwMask=CFM_BACKCOLOR | CFM_COLOR;
richedit2->SetSelectionCharFormat(cfm); CDialog::OnPaint();
}void CMyDialog::OnLButtonDown(UINT nFlags, CPoint point)
{ richedit2->SetSel(nStartChar/3,nEndChar/3);
flag=1;
Invalidate();
}
哎,每次都是必须把光标移动到 Rich Edit控件外才能重绘,还要按着左键。
好像光标在空间范围里面就不响应消息。
糟糕透了!都搞了 6 个小时了。
真是麻烦。
继续做一下,再做不出来就不搞了。
preallocate,我也学习ing谢谢!