首页 > 解决方案 > 在 C 中有效读取展平文件

问题描述

我正在尝试读取 C 中每行一个浮点数的大文件。为此,我将下面的代码放在一起。在小数据上进行测试时效果很好。但是,这种方式读取 6 亿个数字时,速度非常慢。关于如何加快速度的任何想法?我正在通过 python 生成原始文件,因此重新格式化数据(例如,在一行中有多个数字,用逗号分隔)也是一种选择。任何有关此方法为何如此缓慢的见解将不胜感激。

void read_file(float *W)
{
   FILE *fp;

   int i = 0;

// In this file, one row should contain only one NUMBER!!
// So flatten the matrix.
   if (fp = fopen("C:\\Users\\rohit\\Documents\\GitHub\\base\\numerical\\c\\ReadFile1\\Debug\\data.txt", "r")) {
      while (fscanf(fp, "%f", &W[i]) != EOF) {
         ++i;
      }
      fclose(fp);
   }

   fclose(fp);

   scanf("%d",&i);    
}

标签: cperformancefileio

解决方案


(评论:这是我的第二个答案。)我看到 OP 在评论中询问:

您是否碰巧在 C 中有一个示例来读取二进制浮点数?

二进制版本会让任何 ascii 版本都被淘汰。而且更短。

此处 OP 的函数签名已更改为在 return 中包含最大浮点数W,并返回从文件中实际读取的数字。

size_t read_file(float *W, size_t maxlen)
{
    FILE *fp = fopen("C:\\Users\\rohit\\Documents\\GitHub\\base\\numerical\\c\\ReadFile1\\Debug\\data.txt", "r");
    return fp ? fread(W, sizeof(float), maxlen, fp) : 0;
}

或者对于更快的东西你可以使用mmap... 。但这在 Windows 上不可用。


补充:但是,无缓冲 I/O 可能会更快。以下函数使用单个malloc和单个无缓冲read将文件复制到堆中。(注意:尚未对大文件进行测试;可能需要open64。)

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>  
#include <sys/stat.h>  

void *readFileToHeap(const char *file, int *len) {
   void *retval = 0;
   ssize_t cnt;
   struct stat st;
   const int fd = open(file, O_RDONLY, 0);
   if (fd < 0)
      return printf("Cannot open %s\n", file), (void *)0;
   if (fstat(fd, &st))
      return perror("fstat()"), close(fd), (void *)0;
   if (!(retval = malloc(st.st_size)))
      return perror("malloc()"), close(fd), (void *)0;
   cnt = read(fd, retval, st.st_size);
   close(fd); // not the best: could clobber errno
   if (cnt < 0)
      return perror("read()"), free(retval), (void *)0;
   if (cnt != st.st_size)
      return printf("Partial read %d\n", cnt), free(retval), (void *)0;
   *len = cnt;
   return retval;
}

推荐阅读