【问题标题】:Overwrite only a specific part of a file仅覆盖文件的特定部分
【发布时间】:2011-03-30 13:40:48
【问题描述】:

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

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

Guest list:
jon
mary
paul
luke
Table list:

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

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

谢谢!

编辑:

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

【问题讨论】:

  • 你能链接到你不明白的答案吗?另外,你能把你的整个文件加载到内存中吗?还是有那么大?
  • 我不会费心尝试更新文件的某些部分 - 只需读入全部内容并再次写出全部内容。更新部分文本文件太容易出错且乏味。
  • @Space 是这个问题:stackoverflow.com/questions/2530274/… 我明白了一般要做的事情,但我不知道如何跳到不同的行。是的,我可以将整个文件加载到内存中。 @trojanfoe 完全覆盖文件,你的意思是?

标签: c++ io fstream


【解决方案1】:

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

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

【讨论】:

  • 我会尝试做类似的事情。尽管如此,我还是想确保我做得正确,因为我几乎没有使用 C++ 处理文件的经验。如果您可以编写一个执行您提到的步骤的代码,我将不胜感激。谢谢!
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    #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_list_end 仍然有效,即使我们添加或删除了客人。请记住,列表中的findremove 具有线性复杂性,因此如果文件很长,这可能会很昂贵。

    此代码还假定客人后跟桌子列表。如果情况发生变化,您必须修改 find-statement。

    【讨论】:

    • 谢谢!我只想问一件事:如果您不知道 Guest list 和 Table list 之间的数据是什么并且 Guest list 不在文件开头怎么办?
    猜你喜欢
    • 2011-11-27
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-27
    • 1970-01-01
    相关资源
    最近更新 更多