仅覆盖文件的特定部分

时间:2011-03-30 13:40:48

标签: c++ io fstream

我知道这是asked once,但我不明白答案。

假设我有一个这样的文件:

Guest list:
jon
mary
paul
luke
Table list:

然后,例如,我想更改来宾的名字。我知道我需要搜索字符串“Guest list”,然后覆盖“Guest list”和“Table list”之间的所有内容。但我不知道该怎么做。

我正在使用C ++,我更喜欢使用fstream:D

谢谢!

编辑:

似乎编写一个全新的文件是文件相对较小的最佳方法。我可能会将此方法用于我现在想做的事情。但我仍然对如何处理需要更新大文件的情况感兴趣。

3 个答案:

答案 0 :(得分:3)

如果新的访客姓名与旧访客姓名的长度不完全匹配,则无法就地执行替换,最好使用临时文件。

  • 逐行阅读原始文件,直到找到“Guest list:”分隔符,将每行复制到临时文件。
  • 将新访客列表写入临时文件。
  • 从原始文件中读取行,直到找到“表格列表:”分隔符。
  • 逐行读取原始文件直到结束,将每行复制到临时文件。
  • 删除原始文件。 (或者重命名为其名称添加备份扩展名。)
  • 将临时文件重命名为原始文件的名称。

答案 1 :(得分:0)

如果你可以将整个文件放在内存中(正如Space指出的那样),请使用ifstream读取它,并使用ofstream写出“Guest List”行,并且所有的新名字。这不是唯一的方法,但它是最方便的。

答案 2 :(得分:0)

所以,这里有一些代码(这些问题并不像初看起来那么简单):

#include <iostream>
#include <fstream>
#include <list>
#include <string>
#include <iterator>
#include <algorithm>

int main()
{
    std::list<std::string> data;

    // load data from file line-by-line
    { // you can make this a function if you want
        std::ifstream file("test.txt");
        std::string buffer;
        while(std::getline(file, buffer))
            data.push_back(buffer);
    } // end of scope - file gets closed for us

    // find end of guest-list - this is where new guests are added
    std::list<std::string>::iterator guest_list_end = 
        std::find(data.begin(), data.end(), "Table list:");

    data.remove("mary"); // remove mary from guest-list
    data.insert(guest_list_end, "betty"); // append betty to guest-list
    data.insert(guest_list_end, "harry"); // append harry to guest-list

    // write entire file back
    std::ofstream file("test.txt");
    std::copy(data.begin(), data.end(), 
        std::ostream_iterator<std::string>(file, "\n"));
}

由于此示例使用std::list,因此即使我们添加或删除guest虚拟机,迭代器guest_list_end仍然有效。请注意,列表中的findremove具有线性复杂性,因此如果文件很长,则可能会很昂贵。

此代码还假定guest虚拟机后跟表列表。如果更改,则必须修改find - 语句。