首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >高效读取C语言中的扁平化文件

高效读取C语言中的扁平化文件
EN

Stack Overflow用户
提问于 2018-08-03 02:27:48
回答 1查看 124关注 0票数 4

我正在尝试读取一个大文件,它在C中每行有一个浮点数。为此,我将下面的代码组合在一起。当在小数据上测试时,它工作得很好。然而,当以这种方式读取6亿个数字时,速度非常慢。有什么建议可以让我加快速度吗?我通过python生成原始文件,因此也可以重新格式化数据(例如,在一行中用逗号分隔多个数字)。任何对此方法如此缓慢的原因的洞察都将不胜感激。

代码语言:javascript
复制
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);    
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-03 02:51:08

几年前我也遇到过类似的问题。解决方案是用fgetsstrtod替换fscanf。如果我没记错的话,这带来了超过10倍的改进。

所以你的循环:

代码语言:javascript
复制
  while (fscanf(fp, "%f", &W[i]) != EOF) {
     ++i;
  }

应该看起来像这样:

代码语言:javascript
复制
  while (fgets(buf, sizeof buf, fp)) {
     W[i++] = strtod(buf, 0);
  }

编辑:错误检查总是一个好主意。因此,加上这一点,简单的两行代码增长到大约十行:

代码语言:javascript
复制
  char buf[80];
  errno = 0;
  while (!errno && fgets(buf, sizeof buf, fp)) {
      W[i++] = strtod(buf, 0);
  }
  if (errno) { // Maybe ERANGE or EINVAL from strtod, or a read error like EINTR
      int save = errno;
      printf("errno=%d reading line %d\n", save, i); // or perror()
      exit(1);
  }

编辑2:关于错误检查,输入文件可能很容易包含诸如naninf之类的文本,可能来自上游的某个bug。但是strtodfscanf非常乐意解析这些内容。这可能会在您的代码中导致神秘的问题。

但它很容易检查。添加代码:

代码语言:javascript
复制
  int bad = 0;
  for (int j = 0; j < i; j++)
      bad += !isnormal(W[j]); // check for nan, inf, etc.
  if (bad) {
     // ... handle error
  }

将其放在一个单独的、简单的循环中可以使编译器更容易优化(理论上),特别是当您使用#pragma GCC optimize ("unroll-loops")之类的东西时。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51660090

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档