部分写入文件 - C ++

时间:2011-08-23 05:52:35

标签: c++ fstream

我正在使用C ++中的VS2010。

我有一个名为Room的课程。房间有x和y属性,然后是一堆其他属性。

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

$ X $ Y $ $名称大小$类型$ $状态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();

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

3 个答案:

答案 0 :(得分:1)

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

如果您有一个公式可以直接从x和y坐标告诉您文件中房间的位置,那么它真的会让您的生活更轻松。

,您可以寻找合适的地方,而不必循环浏览文件以寻找合适的房间

答案 1 :(得分:0)

只重写文件中的某些数据需要两件事:

  • 你必须知道文件中从哪里开始写作的位置。然后,您可以像使用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打开文件。否则,您可能(部分)丢失文件的内容。

答案 2 :(得分:0)

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

  • 通过重载&gt;&gt;向您的Room类添加序列化和&lt;&lt;运营商
  • 在执行开始时将条目列表读入内存(例如,使用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;    
}