在C中读取和处理大于0.5GB的大型数据文件的最佳方法

在C中读取和处理大于0.5GB的大型数据文件的最佳方法,c,performance,csv,large-files,C,Performance,Csv,Large Files,我需要用C编写代码,可以读取包含双值数据矩阵的大型csv文件。我必须逐列阅读,而且我事先没有关于文件中行数和列数的信息。 在时间和内存方面,用C语言处理它最有效的方法是什么?我基本上需要分别处理每一列,但如果阅读效率更高,可以按行阅读 如果以前有人问过,请告诉我答案。 谢谢csv文件是一个文本文件。通常,每行由行尾字符分隔,逗号分隔列。您必须扫描每一行以识别列 有很多方法可以解决这个问题。您的解决方案实际上取决于您是否习惯使用的例程 我会使用malloc分配尽可能大的缓冲区,使用fread将cs

我需要用C编写代码,可以读取包含双值数据矩阵的大型csv文件。我必须逐列阅读,而且我事先没有关于文件中行数和列数的信息。 在时间和内存方面,用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是基于行的、基于行的,并且您需要处理列,因此最好的方法是将整个文件放在内存中:请求文件大小并使用malloc分配该内存块。阅读第一行并确定列数“numcols”。现在重新处理文件并为每一行分配一个带有“numcols”项的数组,该数组将指向行中列的开头,因为每个数字可以有不同的位数,所以不能假定所有列都从行中相同的偏移量开始。现在,您已经准备好处理列了


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

如果我是你,我会考虑。这取决于你需要做些什么。如果您只需要对第n列求和或求平均值,比如说,不需要一次性将整个文件读入内存,那么您可以一次读取一行,然后进行连续求和。谢谢@Joe。有没有办法知道我能承受多大的缓冲?不过我有16gb的RAM。不管你分配多大的缓冲区,系统都会逐页读取,例如4kb~4096,所以从性能上看,还是一样的。