Мне нужно написать код на C, который мог бы читать большие файлы csv, содержащие большие матрицы данных со значениями double. Мне нужно читать столбец за столбцом, и у меня нет предварительной информации о количестве строк и столбцов в файле. Каков наиболее эффективный способ обработки на языке C - с точки зрения времени и памяти? В основном мне нужно обрабатывать каждый столбец отдельно, но я могу читать по строкам, если чтение более эффективно.

Пожалуйста, направьте меня к ответу, если он был задан ранее. Спасибо

1
Kaur 11 Фев 2015 в 05:55
3
На вашем месте я бы рассмотрел файл с отображением памяти.
 – 
ikh
11 Фев 2015 в 06:04
Это зависит от того, что вам нужно делать с данными. Если вам нужно только суммировать или усреднять n-й столбец, скажем, нет необходимости читать весь файл в память за один раз, вы можете читать строку за раз и делать промежуточный итог.
 – 
Mark Setchell
11 Фев 2015 в 13:42

2 ответа

Поскольку csv основан на строках (на основе строк), и вам нужно обрабатывать столбцы, лучшим способом было бы взять весь файл в памяти: запросите размер файла и выделите этот кусок памяти с помощью malloc. Прочитайте первую строку и определите количество столбцов, 'numcols'. Теперь повторно обработайте файл и выделите для каждой строки массив с записями 'numcols', которые будут указывать на начало столбца в строке (поскольку каждое число может иметь разное количество цифр, вы не можете предположить, что все столбцы начинаются с одного и того же числа). смещение в строке). Теперь вы готовы к обработке ваших столбцов.

Если файл не помещается в памяти, вы можете открыть 'numcols' дополнительные файлы вывода, в которые вы записываете столбцы из строк ввода (например, вы записываете дубли в двоичном формате в файлы), затем перематываете их и обрабатываете каждый файл , который содержит столбец. Если эти выходные файлы помещаются в память, вы можете прочитать их в массив. (Я не говорил, что это эффективно.)

0
Paul Ogilvie 11 Фев 2015 в 13:34

CSV-файл — это текстовый файл. Обычно каждая строка отделяется символами конца строки, а запятые разделяют столбцы. Вы должны сканировать каждую строку, чтобы идентифицировать столбцы.

Есть много способов решить эту проблему. Ваше решение действительно зависит от подпрограмм, которые вам удобно использовать.

Я бы выделил настолько большой буфер, насколько вы можете себе позволить, используя malloc(), читал CSV-файл по частям, используя fread(), и сканировал его, чтобы найти и обработать столбцы.

#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 12 Фев 2015 в 14:23
Спасибо @Джо. Есть ли способ узнать, насколько большой буфер я могу себе позволить? Хотя оперативки у меня 16 гб.
 – 
Kaur
11 Фев 2015 в 10:10
Независимо от размера буфера, который вы выделяете, система считывает страницу за страницей, например, 4 КБ ~ 4096, поэтому с точки зрения производительности она остается прежней.
 – 
Sridhar Nagarajan
11 Фев 2015 в 19:49