如何在C

时间:2015-09-10 21:27:56

标签: c arrays io fgets

我有一个txt文件,其中包含类型为double的制表符分隔数据。数据文件超过10 GB,所以我只想逐行读取数据,然后进行一些处理。特别地,数据布局为矩阵,例如1001列,以及数百万行。下面只是一个展示布局的假样本。

10.2  30.4  42.9 ... 3232.000 23232.45
...
...
7.234  824.23232 ... 4009.23  230.01
...

对于每一行,我希望将前1000个值存储在数组中,将最后一个值存储在单独的变量中。我是C的新手,所以如果你能指出重要的步骤,那就太好了。

更新

感谢所有宝贵的建议和解决方案。我刚刚想出了一个简单的例子,我只是从一个txt文件中逐行读取一个3乘4的矩阵。对于每一行,前3个元素存储在x中,最后一个元素存储在向量y中。因此xn-by-p矩阵,n=p=3y1-by-3向量。

以下是我的数据文件和我的代码。

数据文件:

1.112272    -0.345324   0.608056    0.641006
-0.358203   0.300349    -1.113812   -0.321359
0.155588    2.081781    0.038588    -0.562489

我的代码:

#include<math.h>
#include <stdlib.h>
#include<stdio.h>
#include <string.h>

#define n 3
#define p 3

void main() {

    FILE *fpt;
    fpt = fopen("./data_temp.txt", "r");    

    char line[n*(p+1)*sizeof(double)];
    char *token;
    double *x;
    x = malloc(n*p*sizeof(double));
    double y[n];

    int index = 0;
    int xind = 0;
    int yind = 0;

    while(fgets(line, sizeof(line), fpt)) {
        //printf("%d\n", sizeof(line));
        //printf("%s\n", line);

        token = strtok(line, "\t");
        while(token != NULL) {
            printf("%s\n", token);

            if((index+1) % (p+1) == 0) { // the last element in each line;
                yind = (index + 1) / (p+1) - 1; // get index for y vector;
                sscanf(token, "%lf", &(y[yind]));
            } else {
                sscanf(token, "%lf", &(x[xind]));
                xind++;
            }
            //sscanf(token, "%lf", &(x[index]));
            index++;
            token = strtok(NULL, "\t");
        } 
    }

    int i = 0;
    int j = 0;
    puts("Print x matrix:");
    for(i = 0; i < n*p; i++) {
        printf("%f\n", x[i]);
    }
    printf("\n");

    puts("Print y vector:");
    for(j = 0; j < n; j++) {
        printf("%f\t", y[j]);
    }
    printf("\n");
    free(x);
    fclose(fpt);
}

如上所述,如果我将data_temp.txt替换为原始的10 GB数据文件(当然,在必要时更改np和其他一些代码的值,那么事情将会有效。 )

如果你能帮助我,我还有其他问题。

  1. 我首先将char line[]初始化为char line[(p+1)*sizeof(double)](注意不要乘以n)。但该线无法完全读取。我怎么能为一行分配内存?长度是多少?我认为它是(p+1)*sizeof(double),因为每行都有(p+1)个双打。我还应该为\t\n分配内存吗?如果是这样,怎么样?
  2. 代码看起来合情合理吗?我怎么能让它更高效,因为这段代码将在数百万行上执行?
  3. 如果我不知道原始10 GB文件中的列数或行数,我怎样才能快速计算行数和列数?
  4. 我再次成为C的新手,任何评论都非常感谢。非常感谢!

2 个答案:

答案 0 :(得分:1)

第一路

使用fread将文件以块的形式读入预分配的缓冲区。

第二路

使用mmap将文件映射到您的进程内存空间,然后将指针移到文件上。

答案 1 :(得分:0)

第三路

由于您的文件由行分隔,请使用fopen打开文件,使用setvbuf或类似设置大于约10行左右的缓冲区大小,然后逐行读取文件使用fgets行。

要更快地读取文件,请open使用O_DIRECT(假设是Linux),然后使用fdopen获取打开文件的FILE *,然后使用setvbuf设置页面对齐的缓冲区。这样做将允许您绕过内核页面缓存 - 如果您的系统的实现以这种方式使用直接IO成功运行。 (指导IO可能有很多限制)

相关问题