之前写了个opencv读取大矩阵的问题,这次遇到一个更大的矩阵,不想用opencv格式化读文件,故直接采用c++读取。
首先c++读取文件的几种方式可以参考“探寻C++最快的读取文件的方案”(1)一文,而其中提到的内存映射方法可以参考“windows笔记-内存映射文件”(2)一文。
输入对象是一个50×71028的浮点数矩阵,保存为.txt文件,共55mb,单纯采用fstream格式化读取需要1分钟,而采用scanf读入需要15秒。故决定采取文(1)中介绍的读入整个文件再处理的方法,代码如下:
int main()
{
int start = clock();
readdata1();
printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC);
printf("%f",a[0][3]);
return 0;
}void readdata1()
{
freopen("p_test.txt","rb",stdin);
int len = fread(buf,1,MAXS,stdin);
buf[len] = '\0';
char *p;
const char *split=" ";
p=strtok(buf,split);
int i=0,j=0;
while(p!=NULL)
{
*(*(a+i)+j)=myatof(p);
j++;
if (j==71028)
{
j=0;
i++;
}
p=strtok(NULL,split);
}
}当然,读取的文件都是char*型的,还必须转换为float型,而系统"stdlib.h"的atof函数正好可以使用。但是考虑到数据文件的范围为-100到100,故参考网上“自己实现的atof()和atoi()代码”一文,改了一个myatof的函数,如下,
double myatof(const char* sptr)
{
double temp=10;
bool ispnum=true;
double ans=0;
if(*sptr=='-')//判断是否是负数
{
ispnum=false;
sptr++;
}
else if(*sptr=='+')//判断是否为正数
{
sptr++;
}
while(*sptr!='\0')//寻找小数点之前的数
{
if(*sptr=='.'){ sptr++;break;}
ans=ans*10+(*sptr-'0');
sptr++;
}
while(*sptr!='\0')//寻找小数点之后的数
{
if (*sptr=='e' || *sptr=='E'){sptr+=3;break;}
ans=ans+(*sptr-'0')/temp;
temp*=10;
sptr++;
}
int cifang=*sptr-'0';
float sumcifang=1;
while(cifang--){sumcifang*=10;}
if(ispnum) return ans*sumcifang;
else return ans*(-1)*sumcifang;
}这样,读取整个文件花费的时间为2.9s,远小于其他方法所需时间。(release版本为1.4s)
版权声明:本文为wzy1990原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。