部分写入文件 - C++

发布于 2024-12-01 01:43:14 字数 1131 浏览 2 评论 0原文

我正在使用 C++ 语言的 VS2010。

我有一个名为“房间”的课程。 Room 有一个 x 和 ay 属性,然后还有一堆其他属性。

我有一个名为 Rooms.txt 的文件,其中包含“房间”对象的一堆属性。它使用自定义语法,因此一个条目可能如下所示:

$x$y$name$size$type$state$EOL@$

所以我可以正常工作:玩家输入 X 和 Y 坐标,并且文本文件中相应条目的值被赋予 Room 对象。

然后我想做的是允许玩家更改其中一些变量并将它们写回到文件中,但我不太清楚如何做。这是迄今为止我最好的努力:

    ifstream inRoom;
ofstream outRoom;
string path = saveRoot;
path.append(ModLoad); // the last two lines get the path for the file to be read/written

inRoom.open(path);
//outRoom.open(path);
string temp;
string temp2;
if(inRoom.bad()){
    cout << "ERROR: Bad save!";
}
while(inRoom.good()){
    temp2 = temp;
    getline(inRoom,temp,'$');
    cout << temp <<inRoom.tellg();
    if ((atoi(temp2.c_str())==myPlayer.X)&&(atoi(temp.c_str())==myPlayer.Y)){
        int seek = inRoom.tellg();
        inRoom.close();
        cout << "Opening " << path << "for writing \n";
        outRoom.open(path);
        outRoom.seekp(seek);
        outRoom.write("HELLO!", 6);
        outRoom.close();
    }
}
inRoom.close();

此外,我需要覆盖这些值,而不是插入新数据。有什么想法吗?

I'm working with VS2010, in C++.

I have a class called Room. Room has an x and a y property, and then a bunch of other properties.

I have a file called Rooms.txt, which contains a bunch of properties for a 'Room' object. It uses a custom syntax, so that one entry might look like this:

$x$y$name$size$type$state$EOL@$

So I've got the following working fine: the player inputs an X and Y coordinate, and the values for the corresponding entry in the text file are given to a Room object.

What I want to then do is allow the player to change some of these variables and write them back to the file, but I can't quite figure out how. This is my best effort so far:

    ifstream inRoom;
ofstream outRoom;
string path = saveRoot;
path.append(ModLoad); // the last two lines get the path for the file to be read/written

inRoom.open(path);
//outRoom.open(path);
string temp;
string temp2;
if(inRoom.bad()){
    cout << "ERROR: Bad save!";
}
while(inRoom.good()){
    temp2 = temp;
    getline(inRoom,temp,'

Also, I need to overwrite the values, not insert new data. Any thoughts?

); cout << temp <<inRoom.tellg(); if ((atoi(temp2.c_str())==myPlayer.X)&&(atoi(temp.c_str())==myPlayer.Y)){ int seek = inRoom.tellg(); inRoom.close(); cout << "Opening " << path << "for writing \n"; outRoom.open(path); outRoom.seekp(seek); outRoom.write("HELLO!", 6); outRoom.close(); } } inRoom.close();

Also, I need to overwrite the values, not insert new data. Any thoughts?

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

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

发布评论

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

评论(3

在你怀里撒娇 2024-12-08 01:43:14

您选择了错误的格式。要进行覆盖,您需要固定宽度格式。因此,无论如何,每个房间在文件中占用相同数量的字节。这样,当您覆盖一个房间时,您可以将新房间放在旧房间的顶部,而不必担心是否必须从整个文件中插入几个字节或删除几个字节。

此外,如果您有一个公式可以直接从 x 和 y 坐标得知文件中房间的位置,那确实会让您的生活更轻松。您可以立即寻找正确的位置,而不必循环遍历文件来寻找正确的房间。

You've chosen the wrong format. For overwriting to work you need a fixed width format. So every room takes up the same number of bytes in your file, no matter what. That way when you overwrite a room you can just put the new room over the top of the old room without worrying about whether you are going to have to insert a few bytes or delete a few bytes from the file as a whole.

Also it would really make you life easier if you had a formula to tell the position of a room in your file directly from the x and y coordinates. Instead of having to loop though the file looking for the right room, you could seek to the right place immediately.

梦太阳 2024-12-08 01:43:14

仅重写文件中的部分数据需要两件事:

  • 您必须知道文件中开始写入的位置。然后您可以像您一样使用 seekp() 转到该位置。
  • 更棘手的是:写入的数据必须完全相同的字节数。否则,您将覆盖以下数据或留下一些旧字节弄乱文件的结构。

要打开文件以重写部分,请使用

file.open(filename, ios::binary|ios::in|ios::out|ios::ate);
file.seekg(0);
// or go to the position to read your data directly
// store that position using tellg()
// read data
// restore position using tellp()
// write data (in exact same length)

我记得这里的技巧是在其末尾打开文件ios::ate。否则您可能(部分)丢失文件的内容。

Rewriting only some data in a file requires two things:

  • You have to know the position in the file where to start writing. Then you can go to that position using seekp() as you did.
  • More tricky: The data written have to be exact the same number of bytes. Otherwise you will overwrite following data or leave some old bytes messing the structure of your file.

To open the file for rewriting parts use

file.open(filename, ios::binary|ios::in|ios::out|ios::ate);
file.seekg(0);
// or go to the position to read your data directly
// store that position using tellg()
// read data
// restore position using tellp()
// write data (in exact same length)

As I remember the trick here is to open the file at its end ios::ate. Otherwise you may (partially) loose the content of the file.

眼泪淡了忧伤 2024-12-08 01:43:14

请记住,您使用的是 C++,因此您必须考虑对象。我要做的是:

  • 通过重载 >> 将序列化添加到您的 Room 类中和<<运算符
  • 在执行开始时将条目列表读入内存(例如使用 std::vector)
  • 当用户输入 X 和 Y 时,在内存中存储的条目列表中查找相应的条目并显示它
  • 如果用户修改某些内容,用新条目替换内存中的现有条目
  • 将整个条目列表写回到文件中,完全替换其内容

这是一个快速而肮脏的代码草稿,只是为了展示这个想法:

#include <vector>
#include <iostream>
#include <fstream>
#include <iterator>

class Room
{
    public:
        int x;
        int y;
        std::string a;
        std::string b;

    private:
        friend std::ostream& operator <<(std::ostream& os, const Room& r);
        friend std::istream& operator >>(std::istream& is, Room& r);

};

std::ostream& operator <<(std::ostream &os, const Room& r)
{
    return os << r.x << r.y << r.a << r.b;
}

std::istream& operator >>(std::istream& is, Room& r)
{
    return is >> r.x >> r.y >> r.a >> r.b;
}


int main()
{
    std::vector<Room> roomList;

    // read the list
    ifstream in("out.txt");
    istream_iterator<Room> ii(in), iieof;
    copy(ii, iieof, back_inserter(roomList));
    in.close();

    // do something with your data
    // ...

    // save the modified list back
    ofstream out("out.txt");
    ostream_iterator<Room> oi(out, "\n");
    copy(roomList.begin(), roomList.end(), oi);
    out.close();

    return 0;    
}

Remember, you are using C++, so you have to think objects. What I'd do is:

  • Add serialization to your Room class by overloading >> and << operators
  • Read the list of entries into the memory (using, for example, std::vector) at the start of the execution
  • When user enters X and Y, lookup corresponging entry in the list of entries stored in the memory and display it
  • If user modifies something, replace the existing entry in the memory with a new one
  • Write the whole list of entries back to the file completely replacing its content

Here's a quick and dirty code draft just to show the idea:

#include <vector>
#include <iostream>
#include <fstream>
#include <iterator>

class Room
{
    public:
        int x;
        int y;
        std::string a;
        std::string b;

    private:
        friend std::ostream& operator <<(std::ostream& os, const Room& r);
        friend std::istream& operator >>(std::istream& is, Room& r);

};

std::ostream& operator <<(std::ostream &os, const Room& r)
{
    return os << r.x << r.y << r.a << r.b;
}

std::istream& operator >>(std::istream& is, Room& r)
{
    return is >> r.x >> r.y >> r.a >> r.b;
}


int main()
{
    std::vector<Room> roomList;

    // read the list
    ifstream in("out.txt");
    istream_iterator<Room> ii(in), iieof;
    copy(ii, iieof, back_inserter(roomList));
    in.close();

    // do something with your data
    // ...

    // save the modified list back
    ofstream out("out.txt");
    ostream_iterator<Room> oi(out, "\n");
    copy(roomList.begin(), roomList.end(), oi);
    out.close();

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