嗯,我想知道是否有一种比使用 fscanf() 更快地读取文件的方法
例如假设我有这个文本
4
55 k
52 o
24 l
523 i
首先我想读取第一个数字,它给出了接下来的行数。
让这个数称为N。
在N之后,我想读取N行,其中有一个整数和一个字符。
使用fscanf
,它会像这样
fscanf(fin,"%d %c",&a,&c);
最佳答案
您几乎不进行任何处理,因此瓶颈可能是文件系统吞吐量。但是,您应该先测量一下是否确实如此。如果您不想使用分析器,您可以只测量应用程序的运行时间。输入文件的大小除以运行时间可用于检查是否已达到文件系统吞吐量限制。
然后,如果您远离上述限制,您可能需要优化读取文件的方式。最好使用 fread()
以较大的 block 读取它,然后使用 sscanf()
处理存储在内存中的缓冲区。
您还可以自己解析缓冲区,这比 *scanf()
更快。
[编辑]
特别是对于德拉科沙:
$ time ./main1
Good entries: 10000000
real 0m3.732s
user 0m3.531s
sys 0m0.109s
$ time ./main2
Good entries: 10000000
real 0m0.605s
user 0m0.496s
sys 0m0.094s
所以优化版本的速度约为 127MB/s,这可能是我的文件系统的瓶颈,或者操作系统可能将文件缓存在 RAM 中。原始版本约为 20MB/s。
使用 80MB 文件进行测试:
10000000
1234 a
1234 a
...
main1.c
#include <stdio.h>
int ok = 0;
void processEntry(int a, char c) {
if (a == 1234 && c == 'a') {
++ok;
}
}
int main(int argc, char **argv) {
FILE *f = fopen("data.txt", "r");
int total = 0;
int a;
char c;
int i = 0;
fscanf(f, "%d", &total);
for (i = 0; i < total; ++i) {
if (2 != fscanf(f, "%d %c", &a, &c)) {
fclose(f);
return 1;
}
processEntry(a, c);
}
fclose(f);
printf("Good entries: %d\n", ok);
return (ok == total) ? 0 : 1;
}
main2.c
#include <stdio.h>
#include <stdlib.h>
int ok = 0;
void processEntry(int a, char c) {
if (a == 1234 && c == 'a') {
++ok;
}
}
int main(int argc, char **argv) {
FILE *f = fopen("data.txt", "r");
int total = 0;
int a;
char c;
int i = 0;
char *numberPtr = NULL;
char buf[2048];
size_t toProcess = sizeof(buf);
int state = 0;
int fileLength, lengthLeft;
fseek(f, 0, SEEK_END);
fileLength = ftell(f);
fseek(f, 0, SEEK_SET);
fscanf(f, "%d", &total); // read the first line
lengthLeft = fileLength - ftell(f);
// read other lines using FSM
do {
if (lengthLeft < sizeof(buf)) {
fread(buf, lengthLeft, 1, f);
toProcess = lengthLeft;
} else {
fread(buf, sizeof(buf), 1, f);
toProcess = sizeof(buf);
}
lengthLeft -= toProcess;
for (i = 0; i < toProcess; ++i) {
switch (state) {
case 0:
if (isdigit(buf[i])) {
state = 1;
a = buf[i] - '0';
}
break;
case 1:
if (isdigit(buf[i])) {
a = a * 10 + buf[i] - '0';
} else {
state = 2;
}
break;
case 2:
if (isalpha(buf[i])) {
state = 0;
c = buf[i];
processEntry(a, c);
}
break;
}
}
} while (toProcess == sizeof(buf));
fclose(f);
printf("Good entries: %d\n", ok);
return (ok == total) ? 0 : 1;
}
关于c - 用 C 更快地读取文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4851381/