I'm working with VS2010, in C++.
I have a class called Room. Room has an x and ay 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,'$');
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?
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.
Rewriting only some data in a file requires two things:
seekp()
as you did. 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.
Remember, you are using C++, so you have to think objects. What I'd do is:
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;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.