部分写入文件-C++; 我在VS2010中工作,在C++中。

部分写入文件-C++; 我在VS2010中工作,在C++中。,c++,fstream,C++,Fstream,我有一门课叫Room。房间有一个x和一个y属性,然后是一堆其他属性 我有一个名为Rooms.txt的文件,其中包含一组“Room”对象的属性。它使用自定义语法,因此一个条目可能如下所示: $x$y$name$size$type$state$EOL@$ 因此,我有以下工作正常:播放器输入X和Y坐标,文本文件中相应条目的值被赋予房间对象 然后我想做的是允许播放器更改其中的一些变量并将它们写回文件,但我不太明白如何操作。这是我迄今为止最大的努力: ifstream inRoom; ofstre

我有一门课叫Room。房间有一个x和一个y属性,然后是一堆其他属性

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

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

因此,我有以下工作正常:播放器输入X和Y坐标,文本文件中相应条目的值被赋予房间对象

然后我想做的是允许播放器更改其中的一些变量并将它们写回文件,但我不太明白如何操作。这是我迄今为止最大的努力:

    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();
ifstreaminroom;
室外气流;
字符串路径=saveRoot;
path.append(ModLoad);//最后两行获取要读取/写入的文件的路径
室内开放(路径);
//室外。开放(路径);
字符串温度;
字符串temp2;
if(在room.bad()中){

您可能选择了错误的格式。要使覆盖工作正常,您需要一种固定宽度的格式。因此,无论发生什么情况,每个文件室在文件中占用的字节数都是相同的。这样,当您覆盖一个文件室时,您只需将新文件室放在旧文件室的顶部,而无需担心是否需要插入新文件室几个字节或从整个文件中删除几个字节


此外,如果你有一个公式,可以直接从x和y坐标来判断文件中某个房间的位置,那么你的生活会更轻松。你不必在文件中循环寻找正确的房间,你可以立即找到正确的位置。

你选择了错误的格式。要进行覆盖,你需要一个fixed width format。因此,无论发生什么情况,每个文件室在文件中占用的字节数都是相同的。这样,当您覆盖一个文件室时,您可以将新文件室放在旧文件室的顶部,而不必担心是否需要从整个文件中插入几个字节或删除几个字节


此外,如果你有一个公式,可以直接从x和y坐标来判断文件中某个房间的位置,那么你的生活也会更轻松。你不必在文件中循环寻找正确的房间,而可以立即找到正确的位置。

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

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

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

  • 您必须知道文件中开始写入的位置。然后您可以像以前一样使用
    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)

我记得这个窍门是在其结束时打开文件<> iO::ATE< /COD>。否则你可能(部分地)松开文件的内容。< / P> < P>记住,你使用C++,所以你必须思考对象。我要做的是:


  • 通过重载>和将序列化添加到你的房间类中,记住,你使用C++,所以你必须思考对象。我要做的是:


    • 通过重载>>将序列化添加到Room类中,如果“区域”稀疏,则从xy到seekpos的公式可能会比较复杂。如果区域稀疏,则我会以排序跳转表开始文件。如果“区域”稀疏,则从xy到seekpos的公式可能会比较复杂。如果区域稀疏,则我会以排序跳转表开始文件。