最好的方式来读取和处理大于0.5GB的数据文件C
问题描述:
我需要用C编写代码,它可以读取包含double
值的大型数据矩阵的大型csv文件。我必须逐列阅读,而且我没有关于文件中行数和列数的事先信息。 什么是以C语言处理它的最有效的方式 - 在时间和内存方面?我基本上需要分别处理每列,但如果读取更有效,可以通过阅读行来实现。最好的方式来读取和处理大于0.5GB的数据文件C
如果之前询问过,请直接回答问题。 谢谢
答
csv文件是一个文本文件。通常,每行由行尾字符分隔,逗号分隔列。您必须扫描每一行才能识别列。
有很多方法可以解决这个问题。你的解决方案真的取决于你习惯使用的例程。
我将使用malloc()分配一个尽可能大的缓冲区,使用fread()以块读取csv文件,并扫描它以查找和处理列。
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <malloc.h>
// JFL 11 Feb 15
int main(int argc,char *argv[])
{
int r;
int allocsize,filesize,len;
char *fname;
char *alloc=0;
FILE *fh=0;
if(argc<2)
goto BAIL;
fname=argv[1];
// open file, find size
if(!(fh=fopen(fname,"rb")))
goto BAIL;
fseek(fh,0,SEEK_END); // seek to end
if((filesize=ftell(fh))<0)
goto BAIL;
fseek(fh,0,SEEK_SET);
// alloc buffer
allocsize=16*1024; // max buffer size
if(allocsize>filesize)
allocsize=filesize; // limit to filesize
// 'search' for the largest buffer we can use temporarily
for(;allocsize>1024;allocsize-=1024)
{
if((alloc=malloc(allocsize)))
break; // allocated
} // for
if(!alloc)
{ // try once more, small buffer
allocsize=1024;
if(!(alloc=malloc(allocsize)))
goto BAIL;
}
// read the file
for(;filesize;)
{
len=filesize; // remaining size
if(len>allocsize)
len=allocsize; // limit to buffer size
if(len!=fread(alloc,1,len,fh)) // read
goto BAIL;
filesize-=len; // adjust remaining size
// process len bytes
} // for
r=ftell(fh);
printf("success, read %d bytes\n",r);
BAIL: // common exit point
if(fh)
fclose(fh); // close if opened
if(alloc)
free(alloc); // free if allocated
return 0;
} // main()
答
为CSV是基于行(线为基础的),你需要处理的列,最好的办法是把整个文件在内存中:要求文件大小和allocagte的内存块使用malloc。阅读第一行并确定列数'numcols'。现在重新处理文件并为每一行分配一个包含'numcols'条目的数组,这些条目将指向行中列的起始位置(因为每个数字可以有不同的数字位数,所以您可能不会假定所有列的起始位置都相同在线中偏移)。现在您已准备好处理您的列。
如果文件不适合内存,您可以打开'numcols'附加输出文件,将输入行中的列写入其中(例如,以二进制格式向文件写入双精度),然后倒回并处理每个包含列的文件。如果这些输出文件适合内存,则可以将它们读入一个数组中。 (我没有说这是有效的。)
如果我是你,我会考虑[内存映射文件](http://en.wikipedia.org/wiki/Memory-mapped_file)。 – ikh 2015-02-11 03:04:35
这取决于您需要如何处理数据。如果你只需要对第n列进行求和或求平均值,比如说,不需要一次将整个文件读入内存中,你可以一次读取一行,并执行一次总计。 – 2015-02-11 10:42:00