0

我在用 C 读写文件时遇到性能问题。这是我的问题和解决方案,但速度很慢:

我有一个 ASCII 文件,我认为其中的每一行都是一条记录。我必须根据文件中某个位置存在的特定数字将此文件分成两个。例如,如果位置 10 的数字为 0,则记录转到 file1,如果为 1,则记录转到 file2。

我所做的是打开输入文件和其他两个用于输出文件的文件流。我从输入文件中读取一行,进行比较,然后该行转到 file1 或 file2,然后读取下一条记录。它工作正常,但速度很慢。请建议一种更快的方法。

以下是文件的读取方式:

bytes_read = readline(infile, (void*)buffer, line_size+1);

fwrite 用于写入文件。文件大小约为 50 MB。读取整个输入文件后关闭文件。

4

6 回答 6

1

您几乎已经找到了最快的方法!

  • 你有什么类型的IO?缓冲/无缓冲?
  • 文件有多大?
  • 您是打开/关闭每一行的输出文件,还是保持打开状态?
  • 在输出文件中有任何搜索吗?
  • 读哪一部分慢?写?两个都?

IO 是程序中较慢的部分之一。一些代码可以帮助我们发现任何明显的问题。

于 2012-11-30T22:45:23.283 回答
0

您可以尝试以块的形式读取文件,而不是一次读取一行。块读取可以比逐行读取快得多。如果你能把整件事读入记忆,那就太好了。如果没有,请阅读一个大块,处理它并继续前进。

于 2012-11-30T22:48:56.340 回答
0

我认为您应该将所有文件读入一些数组并处理变量/数组,而不是直接在 IO 上。

当然,如果这是可能的(您的文件很少,而不是数百)。

如果有成百上千的这些文件 - 那么您应该考虑另一种数据存储方法。数据库就是为这样的事情而设计的。

另一种选择是带有 CSV 存储引擎的 MySQL。

mysql.com 上的 CSV 存储引擎

但最后可能会迫使您更改文件结构。

于 2012-11-30T22:50:42.607 回答
0

您可以尝试减少读/写调用的数量。

  1. 尝试一次读取 2k 字节而不是 getline()。如果您的文件不大,甚至可以读取整个文件一次。
  2. 使用缓冲写入。并且不要在每次写入后关闭文件。只有在完成整个文件的写入后才关闭文件。
于 2012-11-30T22:51:27.877 回答
0

如果您正在从文件中读取,那么最好使用 fgets。这会自动为下一个 fget 移动文件指针。

fseek 和 ftell 正在减慢代码中的速度。尝试这个。它应该快得多。

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

int
main()
{
    char line[132];
    int line_num = 0;
    FILE *fp_r, *fp_w1, *fp_w2, *fp_w;

    fp_r = fopen("readfile", "r");
    if (fp_r == NULL) {
        printf("Could not open testfile\n");
        exit(0);
    }

    fp_w1 = fopen("writefile1", "w");
    if (fp_w1 == NULL) {
        printf("Could not open writefile1\n");
        exit(0);
    }

    fp_w2 = fopen("writefile2", "w");
    if (fp_w1 == NULL) {
        printf("Could not open writefile2\n");
        exit(0);
    }

    while (fgets(line, sizeof(line), fp_r) != NULL) {
        line_num++;

        if (*(line+9) == '0') {
            fp_w = fp_w1;
        }
        else if (*(line+9) == '1') {
            fp_w = fp_w2;
        }
        else {
            printf("Exiting - Error at line %d\n", line_num);
            exit(1);
        }

        fprintf(fp_w, line);
    }

    fclose(fp_r);
    fclose(fp_w1);
    fclose(fp_w2);

    exit(0);
}

我使用的读取文件是

01234567 0 This is the line with 0 at position 10
01234567 1 This is the line with 1 at position 10
于 2012-11-30T23:37:00.223 回答
0

在评论中讨论后,我认为您的问题没有简单的答案。

对数千个大尺寸的 CSV 文件进行有效的读写是非常困难的。

发明了具有更好存储引擎的数据库来避免此类性能问题。

也许你应该看看 CSV 引擎在一些开源数据库中是如何设计的。在那里你应该找到(非常复杂的)你的问题的答案:处理许多大 csv 文件的最佳方法是什么。

于 2012-11-30T23:12:51.623 回答