仅覆盖文件的特定部分

发布于 2024-10-28 05:59:18 字数 441 浏览 2 评论 0原文

我知道这是问过一次,但是我不明白答案。

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

Guest list:
jon
mary
paul
luke
Table list:

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

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

谢谢!

编辑:

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

I know this was asked once, but I didn't understand the answer.

Let's say I have a file like this:

Guest list:
jon
mary
paul
luke
Table list:

And then, for example, I want to change the names of the guests. I understood that I need to search for the string "Guest list" and then overwrite everything between "Guest list" and "Table list". But I have no idea how to do that.

I'm using C++, and I prefer using fstream :D

Thanks !

edit:

It seems that writing a completely new file is the best method with relatively small files. I'll probably use this method for what I want to do now. But I'm still really interested in how to handle situations where you need to update a huge file.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

故人爱我别走 2024-11-04 05:59:18

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

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

If the new guest names do not match exactly the length of the old guest names, you can't perform the replacement in-place, it's best to use a temporary file.

  • Read the original file line-by-line until you locate the "Guest list:" delimiter copying each line to the temporary file.
  • Write the new guest list to the temporary file.
  • Read lines from the original file until you locate the "Table list:" delimiter.
  • Read the original file line-by-line until its end, copying each line to the temporary file.
  • Delete the original file. (Or rename it adding a backup extension to its name.)
  • Rename the temporary file to the name of the original file.
淡墨 2024-11-04 05:59:18

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

If you can fit the entire file in memory (as Space had pointed out), read it in using an ifstream, and, using an ofstream write out the "Guest List" line, and all of the new names. It's not the only way, but it's the most convenient.

萌︼了一个春 2024-11-04 05:59:18

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

#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 语句。

So, here is some code (these kinds of problems are not as simple as they seem at first glance):

#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"));
}

Since you this example uses an std::list, the the iterator guest_list_end remains valid, even when we add or remove guests. Keep in mind that find and remove on lists have linear complexity, so if the file is long, this might be costly.

This code also assumes that the guest is followed by the table list. If that changes, you have to modify the find-statement.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文