如何快速读取TXT文件数据

yanasdf789 2014-07-29 02:38:34
有一个500W行的txt 文件,每一行结构都相同,
123.34 ,234.56,456.67,15
223.34 ,234.56,456.67,15
。。。。。。。
如何快速读取这个文件,我读取要500W行要一分钟时间,太慢了 有没有更好办法

GetSysTime(_T("开始测试2:"));
vector<pnode> list2;
string Fname="D:\\点集合\\tt500.txt";
FILE * fp=fopen(Fname.c_str(),"rb+");

if(fp==NULL)
{
MessageBox(NULL,_T("aa"),_T("文件打开失败"),0);
return;
}

while(!feof(fp))
{
pnode nd;
fscanf(fp,"%Lf,%Lf,%Lf,%Lf\n",&nd.x,&nd.y,&nd.z,&nd.i);

//list2.push_back(nd);
}
fclose(fp);

GetSysTime(_T("结束测试2:"));
...全文
706 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2014-08-04
  • 打赏
  • 举报
回复
在文件大小相同的前提下: 读刚读过的文件比头次读没读过的文件快 读转速快的硬盘上的文件比读转速慢的硬盘上的文件快 读没有磁盘碎片的文件比读有磁盘碎片的文件快 读文件不处理比边读边处理快 单线程从头到尾一次读文件比多线程分别读文件各部分快(非固态硬盘上) 读固态硬盘上的文件比读普通硬盘上的文件快
赵4老师 2014-08-04
  • 打赏
  • 举报
回复
您是否希望迅速对您频繁使用的文件进行碎片整理?使用 Contig 优化单个的文件,或者创建连续的新文件。http://technet.microsoft.com/zh-cn/sysinternals/bb897428
shiguojie19892 2014-08-04
  • 打赏
  • 举报
回复
引用 3 楼 yanasdf789 的回复:

	GetSysTime(_T("开始测试3:"));
	FILE *fp=fopen("D:\\点\\tt500.txt","rb+");
	char line[256]={0};
	while(fgets(line,255,fp))
	{
		pnode nd;
		sscanf(line,"%lf,%lf,%lf,",&nd.x,&nd.y,&nd.z);
		double xx=nd.x;
		double yy=nd.y;
		double zz=nd.z;
	}
	fclose(fp);
	GetSysTime(_T("开始测试3:"));
经过测试此次需要35s,但是如果不处理读取的数据,即注释掉 //sscanf(line,"%lf,%lf,%lf,",&nd.x,&nd.y,&nd.z); // double xx=nd.x; // double yy=nd.y; // double zz=nd.z; 只需要1.4s 关键是如何提高sscanf(line,"%lf,%lf,%lf,",&nd.x,&nd.y,&nd.z);的效率 有没有更好的办法将line 转化为结构体?
首先全部到内存,内存处理快,然后再每行到一个固定的结构体。memcpy(struct,fread_line,sizeof(fread_line)); 或者,使用多线程(前提是使用的多核处理器),每个线程分别处理一块。
「已注销」 2014-08-02
  • 打赏
  • 举报
回复
唯一的办法是一次读取1-10M的内容,然后再提取,如果每次读一个,硬盘次数太多,速度也就慢了,500万行,50M的样子,每次读5M,10次就可以读完,读完后,提取计算的时间会很少,所以你这个过程大概5s内完成
whoho 2014-07-30
  • 打赏
  • 举报
回复
引用 6 楼 jerry_dqh 的回复:
建议以二进制的形式存储,少一个sscanf的过程。 还有一个问题是,你将下面的这些注释后, //sscanf(line,"%lf,%lf,%lf,",&nd.x,&nd.y,&nd.z); // double xx=nd.x; // double yy=nd.y; // double zz=nd.z; 要注意这个测试的1.4s的可靠性,我怀疑这个1.4s的准确度,因为你将这些注释掉,那么就是循环中没有做任何的操作,导致有可能编译器做了优化。可以反汇编看一下。是否开了o2优化选项? pnode nd;,double xx 这些也要放到循环外面去定义,不要放在循环内。
1.4s倒是可以认为是可靠的,我用的是“反证法”,如果说编译器优化掉读文件的代码,那么你重新看一下整个程序, 基本上没有什么操作,根本用不了1.4s的执行时间,所以说优化掉读文件是不存在的情况
whoho 2014-07-30
  • 打赏
  • 举报
回复
引用 10 楼 truexf 的回复:
每天都有人提出用多线程读写磁盘的馊主意。
正解!磁盘是没办法做到那种并发的,呵呵 不过这里倒是可以考虑解析的时候起几个线程来,按照楼主描述,他好像解析时间跟不上
超级能量泡泡 2014-07-30
  • 打赏
  • 举报
回复
不会是搞什么大数据,或者量化金融之类的吧
排山和倒海 2014-07-29
  • 打赏
  • 举报
回复
mark一下,不错的帖子,我觉的慢主要慢在处理吧,5M的数据不大的,我觉的你可以把数据都读如数组,然后处理的时候多个线程进行处理吧
「已注销」 2014-07-29
  • 打赏
  • 举报
回复
每天都有人提出用多线程读写磁盘的馊主意。
mujiok2003 2014-07-29
  • 打赏
  • 举报
回复
试试把文件流的buf调大点, 每次scanf多行
ma100 2014-07-29
  • 打赏
  • 举报
回复
1. 如果是机械硬盘,开多线程反而慢 2. 500w也就5M,一行算100个字符也可以接受(Windows),所以先全读内存里
taodm 2014-07-29
  • 打赏
  • 举报
回复
读取这么大的文件才需要1分钟,这有什么好嫌慢的。你再优化,提高也有限的。 阐述你的原始需求,才可能得到正确的解。
碼上道 2014-07-29
  • 打赏
  • 举报
回复
建议以二进制的形式存储,少一个sscanf的过程。 还有一个问题是,你将下面的这些注释后, //sscanf(line,"%lf,%lf,%lf,",&nd.x,&nd.y,&nd.z); // double xx=nd.x; // double yy=nd.y; // double zz=nd.z; 要注意这个测试的1.4s的可靠性,我怀疑这个1.4s的准确度,因为你将这些注释掉,那么就是循环中没有做任何的操作,导致有可能编译器做了优化。可以反汇编看一下。是否开了o2优化选项? pnode nd;,double xx 这些也要放到循环外面去定义,不要放在循环内。
whoho 2014-07-29
  • 打赏
  • 举报
回复
一个建议方案: 不用fopen/fscanf这些,而用操作系统的API直接进行; 数据记录定长吗?不定长想办法改成定长(比如补空格),然后每次加载定量的数据行,不是一行,是N行,进内存后再解析 N的取值你根据你测试的结果选一个合适的 我实在想象不出为什么几百万行的数据居然还是用不定长文本进行存储 以上方案如果还不能满足性能,那就把文本化的浮点数改为二进制存储
我看你有戏 2014-07-29
  • 打赏
  • 举报
回复
一次行load到内存吧
yanasdf789 2014-07-29
  • 打赏
  • 举报
回复

	GetSysTime(_T("开始测试3:"));
	FILE *fp=fopen("D:\\点\\tt500.txt","rb+");
	char line[256]={0};
	while(fgets(line,255,fp))
	{
		pnode nd;
		sscanf(line,"%lf,%lf,%lf,",&nd.x,&nd.y,&nd.z);
		double xx=nd.x;
		double yy=nd.y;
		double zz=nd.z;
	}
	fclose(fp);
	GetSysTime(_T("开始测试3:"));
经过测试此次需要35s,但是如果不处理读取的数据,即注释掉 //sscanf(line,"%lf,%lf,%lf,",&nd.x,&nd.y,&nd.z); // double xx=nd.x; // double yy=nd.y; // double zz=nd.z; 只需要1.4s 关键是如何提高sscanf(line,"%lf,%lf,%lf,",&nd.x,&nd.y,&nd.z);的效率 有没有更好的办法将line 转化为结构体?
tingyuyiye01 2014-07-29
  • 打赏
  • 举报
回复
直接多开几个线程,并发读取就好了
fishion 2014-07-29
  • 打赏
  • 举报
回复
创建内存映射空间,一次读取内存中再处理,如果要用多线程,可以将数据平等分割,判断取出首条数据,然后再在多线程中出现

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧