0

我正在编写一个处理非常大的用户生成的输入文件的应用程序。该程序将复制大约 95% 的文件,有效地复制它并在副本中切换一些单词和值,然后将副本(以块的形式)附加到原始文件中,这样每个块(由 10 到 50行)在原始块之后是复制和修改的块,然后是下一个原始块,依此类推。用户生成的输入符合某种格式,原始文件中的任何行都不太可能超过 100 个字符。

哪种方法更好?

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

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

我最关心程序的效率,因为输入文件将达到 25,000 行,每行大约 50 个字符。

4

2 回答 2

4

如果您有内存限制,或者您想要一种通用方法,请从一个文件指针将字节读入缓冲区,进行更改,然后在缓冲区已满时将缓冲区写出到第二个文件指针。如果您在第一个指针上到达 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 *copyBuffer它会被realloc()-ed 到两倍大小,以处理累积的编辑。这样,您就可以将昂贵realloc()的通话费用降至最低。

不知道为什么这被否决了,但它是一种非常可靠的方法,可以处理大量数据。无论如何,希望这对遇到这个问题的人有所帮助。

于 2012-11-21T17:52:10.407 回答
1

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

于 2012-11-21T17:03:40.403 回答