载入文档很慢 要近2分多钟
这是一段载入词库的代码 并将词库里的数据放入链表,但是效率极低,将432KB的 txt文本文档的内容载入并存入链表要近两分钟时间。 这里该怎么优化?//文档内容均为中文。
#include <iostream>
#include <fstream>//文件类的头文件
#include <afx.h>// MFC类的头文件
#include <stdio.h>
#include <afxwin.h> //框架窗口的头文件
#include <afxtempl.h>//CList类的头文件
#include <string>
using namespace std;
int InitialLinkList(FILE * const file,CList<char *,char*> * const clist,int CharCount);//初始化链表
CList<char *,char*> listTwo;
int main()
{
string Sentence ="";
FILE * fileOne = fopen("TwoChar1.txt","r");
if(InitialLinkList(fileOne,&listTwo,2*2+1) == -1)//2个汉字的词库中文占5个字节。
return -1;//如果返回-1表示词库一打开失败 ,主函数返回,链表初始化不成功。
return 0;
}
int InitialLinkList(FILE * const file,CList<char *,char*> * const clist,int CharSum)
{
if(file == NULL)
return -1;
while(!feof(file))
{
char * strbuf = new char[CharSum];//初始化指定的链表
memset(strbuf,0,CharSum);
fgets(strbuf,CharSum,file);//从文件中获取CharSum大小数据写入堆中
clist ->AddTail(strbuf);//将堆的指针压入链表
}
fclose(file);//关闭词库文件。
}
[最优解释]
象类似这种语法分析,语句分析什么的用映射文件来做比较好:
1.CreateFile来打开文件
2.CreateFileMapping建立映射文件
3.MapViewOfFile进行视图映射
就这三个函数行了,具体用法网上有好使的用法
[其他解释]
不见得吧,虽然windows有缓存机制,可是依赖于未文档化的缓存并不可靠
建议试试一次读完,然后解析
如果这样还觉得慢,那干脆直接用FileMapping吧
[其他解释]
那也没有必要,你用二进制方式打开,用_filelength(fp)就能得到文件的大小。
不过这个是微软扩展的函数,标准C的方法是fseek(fp,0,SEEK_END);然后size=ftell(fp);就是文件的大小了。
根据这个大小直接malloc一块空间,然后把文件整个读入。然后再进行处理。
[其他解释]
我的内存块的意思是这样的:
二字词表起始指针words2指向下面这个块的开始处:
"苹果香蕉橘子......"
三字词表起始指针words3指向下面这个块的开始处:
”动物园游戏机计算机......“
当然实际的词是经过排序的,也就是将这个词无间隔的连续存储,起始就是一个大数组,地址很容易计算,
链表是多余的。
[其他解释]
你一次读取到内存缓冲区中,然后再解析数据不行吗?
[其他解释]
“将词库里的数据放入链表”是指用户的常规操作--装载词库么?
while(!feof(file) 循环中,你到底想做什么,为什么这么写?
[其他解释]
其实2楼说的那样,速度应该差不多,因为Windows是由缓存机制的,所以就算你不读到内存缓冲区,还是相当于在内存解析。
主要是你的数据结构不对,词库存储的方式不对,不能用文本文件。应该用一条条struct写入的二进制的记录文件,而且是应该有索引或排序的。用结构的好处时限定每个元素的长度,这样读取时就可以直接memcpy而不需要逐个字符处理。
读内存时直接转换为二叉查找树之类的,肯定效率高很多。
[其他解释]
个人估计时间是花在了fget上
400多K,全读到内存不算问题,解析完记得及时释放掉就行
FileMapping就是文件映射,允许你像使用指针一样去操作硬盘上的文件
[其他解释]
因为C语言的标准读取方式必须要转换行符等,就算你不fgets,照样还是有一个逐个字符处理的过程,这个绝对拖慢速度。所以LZ应该以二进制方式读入,如果能预先排序或者做成查找树的结构,可以直接跳过构造内存结构的过程。
而LZ为什么要存入链表呢?一个地址指针要4个字节加上一个结束符,相当于多浪费了一倍的内存空间,而解析指针也是多余的。
我有一个建议,你可以把二字词、三字词分别用不同的内存块。每个块里都是等长的词,连续存储(无间隔线性表),那么每个词的起始处很容易计算。这样堆就不容易碎片化的。只要你的词经过排序的话,或者建立一个索引树的话,肯定快很多。
[其他解释]
看看FreePy的词库结构
[其他解释]
读完再操作,会快很多
[其他解释]
也可以:
下载我的‘MyFreePy.rar’
http://download.csdn.net/detail/schlafenhamster/1690580
[其他解释]
你一次读取到内存缓冲区中,然后再解析数据不行吗?
[其他解释]
内存缓冲区是什么意思? 是一个变量吗? 因为我的词库是一行一个词语的。一行都是两个字的词语。 保存为TXT文档,大小大概是489KB
我将这个文件中的词语一行一行的读取到链表中。
结果这段时间花了近2分钟。
FileMapping是什么?
[其他解释]
采用链表存储主要是因为我无法确定文件中到底有多少行词语。 既然是未知的,所以我采用了链表。
多谢你的建议,但我不清楚你的内存块的意思。我想如果你说的是变量的话! 那就是链表比较合适吧!
呵呵! 不是很了解你们的说法,不好意思啊!
[其他解释]
你的建议很给力,我试了下词库载入时间几乎可以忽略。
但是我们老师要求我们对文章进行分词,套他说要建立索引树! 这个我觉得很难想象那棵树究竟是怎么样的? 你能给给我讲讲吗?
[其他解释]
恩 ,是的我觉得我很需要借鉴下其他人写的词库的结构。
[其他解释]
谢谢你的建议,我会去尝试的! 但是现在我纠结的是建立一个索引树的问题。
能告诉我这个索引树的结构吗?
12楼说的那个FreePy我在网上没找到他的相关资料。
[其他解释]
能不能告诉我,这个索引树的结构。
[其他解释]
能给段代码看看嘛? 网上的代码似乎都是针对64位系统的。
__int64 qwFileSize = 0x4000000;
__int64 qwFileOffset = 0;
__int64 T = 600 * sys_info.dwAllocationGranularity;