【问题标题】:Modifying a text file without reading into memory修改文本文件而不读入内存
【发布时间】:2014-07-07 16:20:02
【问题描述】:

我试图找出一种方法来修改文本文件(特别是删除特定行),而无需将大部分文件读入内存或重写整个文件。这里所说的文件比主内存大约 15-50 Gigs。

附:我正在使用 Linux。

【问题讨论】:

  • 是的,当你补充说它是一个文本文件时,我想这么多。
  • 不,你很擅长 SOL。
  • 这只是一个想法,但是如果您对文件或其部分进行内存映射并在返回的指针上使用 memmovememset 之类的东西呢?应该允许您直接写入和擦除文件吗?
  • @Brandon,当一行被删除(或添加)并且大小发生变化时会发生什么?做不到。至少不会发明一些令人难以置信的复杂方案。
  • @Duck 我明白你的意思。我没有考虑尺寸变化。

标签: linux text-files


【解决方案1】:

您将无法绕过制作新文件,因此只需硬着头皮去做。使用grep使用适当的选项并将结果加入第二个文件:

$ grep -fv patternsToExcludeFromInput input > output

另一种方法是将模式放入例如哈希表 (Perl)、字典 (Python) 或 unordered_map (C++) 中,并处理输入文件的每一行以查找匹配项。

如果没有匹配,则将该行打印到标准输出流(您可以通过管道传输到常规文件)。您的内存使用将主要限于哈希表和您正在查询的输入行。

【讨论】:

  • 它再次重写整个文件。
  • 只要inputoutput 是不同的文件,你就不应该覆盖任何东西。
【解决方案2】:

如果文件比内存大,sed 是你的朋友。它充当旧文件和新文件之间的过滤器,最后,您只需将新文件重命名为旧名称。语法对于新手来说有点奇怪,但它真的很强大,能够按数字、正则表达式或范围选择行,并应用插入、删除或字符串替换。

【讨论】:

    【解决方案3】:

    您可以在“rw”模式下打开文件并使用 fseek、fread、fwrite 来读/写文件的一部分。您必须注意不要覆盖您尚未阅读的部分。所以删除你向前读写的一行,插入你向后读写的一行(从文件末尾开始)。

    示例

    要从文件开头删除前 100 个字节,您可以执行以下操作:

    FILE *fp = fopen(filename,"rw");
    size_t BLOCK_SIZE = 1024;
    char buffer[BLOCK_SIZE];
    size_t offset = 100;
    fseek(fp,0,SEEK_END);
    size_t length = ftell(fp);
    for (size_t i=0; i< (length-offset+BLOCK_SIZE-1) / BLOCK_SIZE; ++i) {
      fseek(fp,i*BLOCK_SIZE + offset,SEEK_SET);
      size_t count = fread(fp,buffer,sizeof(char),BLOCK_SIZE);
      fseek(fp,i*BLOCK_SIZE,SEEK_SET);
      fwrite(fp,buffer,sizeof(char),count);
    }
    

    【讨论】:

    • fseek() 函数接受三个参数,而您尝试将 fseek() 与一个和两个参数一起使用,因此此代码将无法编译。但是即使正确使用了这个函数,这段代码也不会工作,因为buffer 是未初始化的,你可能只是用fwrite() 调用用垃圾覆盖了文件。
    • @AlexReynolds:Emanuelle 说这是“类似”的伪 c 代码。 buf 先读后写,所以不需要初始化。您是对的,它不会编译并完成工作,但打开“rw”文件并使用 fseek、ftell、fread 和 fwrite 是该问题的正确答案。
    • @AlexReynolds:我将第二个参数添加到 fseek。 Jakub 已经回答了关于缓冲区初始化的问题,这不是问题。
    • 你的答案是错误的。标准的fseek() 函数接受三个参数:pubs.opengroup.org/onlinepubs/000095399/functions/fseek.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    • 1970-01-01
    • 2021-07-10
    • 2017-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多