我有一个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
中。因此x
是n-by-p
矩阵,n=p=3
,y
是1-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数据文件(当然,在必要时更改n
,p
和其他一些代码的值,那么事情将会有效。 )
如果你能帮助我,我还有其他问题。
char line[]
初始化为char line[(p+1)*sizeof(double)]
(注意不要乘以n
)。但该线无法完全读取。我怎么能为一行分配内存?长度是多少?我认为它是(p+1)*sizeof(double)
,因为每行都有(p+1)
个双打。我还应该为\t
和\n
分配内存吗?如果是这样,怎么样?我再次成为C
的新手,任何评论都非常感谢。非常感谢!
答案 0 :(得分:1)
第一路
使用fread
将文件以块的形式读入预分配的缓冲区。
第二路
使用mmap
将文件映射到您的进程内存空间,然后将指针移到文件上。
答案 1 :(得分:0)
第三路
由于您的文件由行分隔,请使用fopen
打开文件,使用setvbuf
或类似设置大于约10行左右的缓冲区大小,然后逐行读取文件使用fgets
行。
要更快地读取文件,请open
使用O_DIRECT
(假设是Linux),然后使用fdopen
获取打开文件的FILE *
,然后使用setvbuf
设置页面对齐的缓冲区。这样做将允许您绕过内核页面缓存 - 如果您的系统的实现以这种方式使用直接IO成功运行。 (指导IO可能有很多限制)