一种读取20000000行文件的有效方法

时间:2018-10-26 17:53:42

标签: c file-io malloc generic-programming

我正在尝试读取一个包含2000万行的巨大数据集,每行中都有一个巨大的数字(实际上,我将数字存储在unsigned long long变量中),例如:{{1} },依此类推...

我为此开发了一个简单的函数,

1774251443, 8453058335, 19672843924

由于锻炼目的,参数void read(char pathToDataset[], void **arrayToFill, int arrayLength) { FILE *dataset = fopen(pathToDataset, "r"); if (dataset == NULL ) { printf("Error while opening the file.\n"); exit(0); // exit failure, it closes the program } int i = 0; /* Prof. suggestion: do a malloc RIGHT HERE, for allocate a * space in memory in which store the element * to insert in the array */ while (i < arrayLength && fscanf(dataset, "%llu", (unsigned long long *)&arrayToFill[i]) != EOF) { // ONLY FOR DEBUG, it will print //printf("line: %d.\n", i); 20ML of lines! /* Prof. suggestion: do another malloc here, * for each element to be read. */ i++; } printf("Read %d lines", i); fclose(dataset); } 的类型为arrayToFill。每个函数都必须对通用类型执行,数组可能会填充每种类型的数据(在此示例中为巨大的数字,但可能包含巨大的字符串,整数等)。

我不明白为什么我必须打2个void**电话,一个电话不够吗?

2 个答案:

答案 0 :(得分:0)

对于您的第一个问题,将malloc视为对存储N个对象的内存的调用,所有对象的大小均为S。当您拥有参数void ** arrayToFill, int arrayLength时,您正在说的是数组将包含大小为arrayLength的{​​{1}}个 个指针。那是第一个分配和对malloc的调用。

但是该数组的成员是指针,它们用于保存数组或本质上用于存储其他对象的指针。对malloc的第一次调用仅分配内存来存储每个数组成员的sizeof(void*),但是数组每个成员的内存都需要它自己的void*调用。

高效的线路阅读

对于您的另一个问题,先进行大量小的内存分配,然后再释放它们(假设您会这样做,否则会泄漏很多内存),这非常慢。但是,与I / O相关任务的性能影响更多地取决于调用次数,而不是所分配的内存数量

让程序将整个文件读入内存,并为2000万个malloc()分配一个数组,或者分配您希望处理的许多整数。这样,您可以解析文件内容,使用unsigned long long中的strtol函数,然后将结果长整形复制到大型数组中。

这样,您只使用2-3个大内存分配和释放。

答案 1 :(得分:0)

我已经提出了这个POSIX解决方案,看看是否有帮助

#include <unistd.h> //for read, write, lseek
#include <stdio.h> //fprintf
#include <fcntl.h> //for open
#include <string.h> //
#include <stdlib.h> // for exit and define
#include <sys/types.h>
#include <sys/stat.h>

int main(int argc, char * argv[])
{
  int fd; // file descriptor
  char * buffer; //pointer for the malloc

  if(argc < 2)
  {
    fprintf(stderr, "Insert the file name as parameter\n");
    exit(EXIT_FAILURE);
  }

if((fd =  open(argv[1], O_RDONLY)) == -1)// opens the file in read-only mode
{
  fprintf(stderr, "Can't open file\n");
  exit(EXIT_FAILURE);
}


off_t bytes = lseek(fd, 0, SEEK_END); // looks at how many bytes the file has
              lseek(fd, 0, SEEK_SET); // returns the file pointer to the start position

buffer = malloc(sizeof(char)*bytes); // allocates enough memory for reading the file

int r = read(fd, buffer, bytes); //reads the file

if(r == -1)
{
  fprintf(stdout, "Error reading\n");
  exit(EXIT_FAILURE);
}

fprintf(stdout, "\n%s", buffer); // prints the file

close(fd);
exit(EXIT_SUCCESS);

}