2015-02-11 60 views
1

我需要用C编写代码,它可以读取包含double值的大型数据矩阵的大型csv文件。我必须逐列阅读,而且我没有关于文件中行数和列数的事先信息。 什么是以C语言处理它的最有效的方式 - 在时间和内存方面?我基本上需要分别处理每列,但如果读取更有效,可以通过阅读行来实现。最好的方式来读取和处理大于0.5GB的数据文件C

如果之前询问过,请直接回答问题。 谢谢

+3

如果我是你,我会考虑[内存映射文件](http://en.wikipedia.org/wiki/Memory-mapped_file)。 – ikh 2015-02-11 03:04:35

+0

这取决于您需要如何处理数据。如果你只需要对第n列进行求和或求平均值,比如说,不需要一次将整个文件读入内存中,你可以一次读取一行,并执行一次总计。 – 2015-02-11 10:42:00

回答

0

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() 
+0

谢谢@Joe。有没有办法知道我可以承受多大的缓冲区?尽管我有16GB的RAM。 – Kaur 2015-02-11 07:10:47

+0

如何分配大尺寸缓冲区,系统逐页读取,例如4kb〜4096,所以表现明智,它仍然是一样的。 – Sridhar 2015-02-11 16:49:41

0

为CSV是基于行(线为基础的),你需要处理的列,最好的办法是把整个文件在内存中:要求文件大小和allocagte的内存块使用malloc。阅读第一行并确定列数'numcols'。现在重新处理文件并为每一行分配一个包含'numcols'条目的数组,这些条目将指向行中列的起始位置(因为每个数字可以有不同的数字位数,所以您可能不会假定所有列的起始位置都相同在线中偏移)。现在您已准备好处理您的列。

如果文件不适合内存,您可以打开'numcols'附加输出文件,将输入行中的列写入其中(例如,以二进制格式向文件写入双精度),然后倒回并处理每个包含列的文件。如果这些输出文件适合内存,则可以将它们读入一个数组中。 (我没有说这是有效的。)

相关问题