用C语言读写大文件的有效方法

时间:2012-11-21 16:57:50

标签: c file

我正在编写一个处理非常大的用户生成的输入文件的应用程序。该程序将复制约95%的文件,有效地复制它并在副本中切换几个单词和值,然后将副本(以块为单位)附加到原始文件,以便每个块(包括10到50之间)在原始的行后面是复制和修改的块,然后是下一个原始块,依此类推。用户生成的输入符合特定格式,原始文件中的任何行都不可能长于100个字符。

哪种方法更好?

  1. 使用一个文件指针并使用保存当前位置的变量以及写入的位置,来回读取和写入文件指针;或

  2. 使用多个文件指针,一个用于阅读,另一个用于写入。

  3. 我主要关注程序的效率,因为输入文件最多可达25,000行,每行大约50个字符。

2 个答案:

答案 0 :(得分:3)

如果您有内存限制,或者您想要通用方法,请从一个文件指针读取缓冲区中的字节,进行更改,并在缓冲区已满时将缓冲区写入第二个文件指针。如果在第一个指针上到达EOF,请进行更改并将缓冲区中的任何内容刷新到输出指针。如果要替换原始文件,请将输出文件复制到输入文件并删除输出文件。这种“原子”方法允许您在删除任何内容之前检查复制操作是否正确。

例如,要处理通常复制任意数量的字节,例如,每次1 MiB:

#define COPY_BUFFER_MAXSIZE 1048576

/* ... */

unsigned char *buffer = NULL;
buffer = malloc(COPY_BUFFER_MAXSIZE);
if (!buffer)
    exit(-1);

FILE *inFp = fopen(inFilename, "r");
fseek(inFp, 0, SEEK_END);
uint64_t fileSize = ftell(inFp);
rewind(inFp);

FILE *outFp = stdout; /* change this if you don't want to write to standard output */

uint64_t outFileSizeCounter = fileSize; 

/* we fread() bytes from inFp in COPY_BUFFER_MAXSIZE increments, until there is nothing left to fread() */

do {
    if (outFileSizeCounter > COPY_BUFFER_MAXSIZE) {
        fread(buffer, 1, (size_t) COPY_BUFFER_MAXSIZE, inFp);
        /* -- make changes to buffer contents at this stage
           -- if you resize the buffer, then copy the buffer and 
              change the following statement to fwrite() the number of 
              bytes in the copy of the buffer */
        fwrite(buffer, 1, (size_t) COPY_BUFFER_MAXSIZE, outFp);
        outFileSizeCounter -= COPY_BUFFER_MAXSIZE;
    }
    else {
        fread(buffer, 1, (size_t) outFileSizeCounter, inFp);
        /* -- make changes to buffer contents at this stage
           -- again, make a copy of buffer if it needs resizing, 
              and adjust the fwrite() statement to change the number 
              of bytes that need writing */
        fwrite(buffer, 1, (size_t) outFileSizeCounter, outFp);
        outFileSizeCounter = 0ULL;
    }
} while (outFileSizeCounter > 0);

free(buffer);

处理调整大小的缓冲区的一种有效方法是保留第二个指针,例如unsigned char *copyBufferrealloc() - 大小的两倍,如果需要,可以处理累积的编辑。这样,您可以将昂贵的realloc()电话限制在最低限度。

不确定为什么这会被投票,但对于使用一般数据量的事情来说,这是一个非常可靠的方法。希望这可以帮助遇到这个问题的人,无论如何。

答案 1 :(得分:1)

25000行* 100个字符= 2.5MB,这不是一个巨大的文件。最快的可能是读取内存中的整个文件并将结果写入新文件并用原始文件替换原文。