reading from .dat file

Pages: 12
Hello. I am currently trying to make a program to keep track of contracts I have in a MMO. It's really inefficient and it's more of a for fun kind of thing since I wanted a new programming project.

My problem is that I cannot figure out how to read objects from a .dat file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ofstream dataOut; //output stream for the data file
	ifstream dataIn; //input stream for data file
	const string FILE = "contracts.dat"; //filename

	dataIn.open(FILE);
	//if it can't be opened, there's a problem and the program won't work. It will most likely be a permission issue.
	if(!dataIn) {
		cout << "File could not be opened/created. Make sure you have the correct permissions. This program will now close \n";
		system("pause");
		exit(1);
	}

	//see if there's anything in it and import the data
	vector<Contract> contracts; //initialize a vector to hold all the contracts
	Contract temp; //initialize a temporary var to store the read data into

	while(!dataIn.eof()){ //read until end of file
		dataIn >> temp; //THIS IS WHERE THE ERROR IS
	}


I get the 'no operator ">>" matches these operands' error. After doing some googling, I found out that it's not overloaded for user created objects... Is there another way to do this?

Thanks
You need to implement the following function:
 
std::istream& operator>>(std::istream&, Contract&);

Engine.obj : error LNK2019: unresolved external symbol "class std::basic_istream<char,struct std::char_traits<char> > & __cdecl operator>>(class std::basic_istream<char,struct std::char_traits<char> > &,class Contract &)" (??5@YAAAV?$basic_istream@DU?$char_traits@D@std@@@std@@AAV01@AAVContract@@@Z) referenced in function _main


I am so confused... I can't even begin to decipher this...
Last edited on
He said you needed to implement the function, which means you need to supply a body for it. The linker is complaining that you told it the function exists, but it doesn't until you define it.
I see... I'm sorry, but I don't understand how to do that. I don't even know what it's trying to accomplish!
Well there may be more to it than just reading in the file. The dat file could be encrypted which would cause more issues as you would have to find how it is encrypted for decrypting it in order to read in the data. Otherwise it may just be a bunch of numbers and letters.
You created 'temp' based on class Contract, but you're not telling it how you want to handle the data. 'temp' is just an object based on a class, it doesn't implicitly know what you want to do with it.

You need to define the path for the data with a function of some sort ( dataIn >> temp.thisFunction; ).

Or, as PanGalactic said - you need to overload the operator >> so the class itself knows how to handle data coming in.

See below for an example based on another operator.

1
2
3
4
5
6
7
8
9
shapeType operator/(const shapeType &x) const
    {  //Overload the operator /
		shapeType temp;

		temp.length = length / x.length;
		temp.width = width / x.width;

		return temp;
	}
Last edited on
Thank you so much for helping me, but I honestly don't understand this at all...

1
2
3
4
istream& operator>>(istream& in, Contract& c) {
	istream temp(_Uninitialized);
	
}


I really don't know what to do with this... Here's my .h file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Contract {
public:
	Contract(); //default constructor
	Contract(string n, vector<string> i, vector<int> a, int p); //Modified constructor
	bool complete; //we want a history of contracts, so don't delete them, just use this identifier to not print them unless specified. Default: false
	void addItem(string n, int a); //add an item to the contract
	void removeItem(int place); //remove an item from the contract at index "place"
	string progress(); //percentage of the contract that has been completed
	int getPrice(); //returns the amount to be paid on completion of the contract
	void getItem(int place); //prints the name of the item, how much is desired, amount obtained and the percentage completed
	string getName(); // returns the name of the clan/person the contract is for
	void addObtained(int place, int amount); //add amount obtained for the item in index "place"
private:
	string name; //name of the ign or clan the contract is with
	vector<string> items; //list of items they want
	vector<int> amount; //list of amount of those items
	vector<int> amountObtained; //list of amount of each item we have for this contract
	int totalPrice; //price to be paid for completion of the contract
};


I don't know how to get the istream to extract something in the form of a Contract object. I've read the istream::operator>> page on this website, but it really doesn't help me understand. I've only been working with c++ for a few months and I don't really understand all the technical parts of it. I won't say no to any spoonfeeding, but I'd much rather understand what's going on!
Last edited on
dataIn >> temp; //THIS IS WHERE THE ERROR IS


because >> doesn't know what to do with a contract. People are telling you to overload the >> operator, which is just to write a function to describe what >> means.

But the first problem is that I assume that this is not a text file. You aren't going to be able to pull integers out of it like you can with a text file. Byte by Byte by word by dword you must do.

so hopefully you know how to parse it and also that it isn't encrypted and/or compressed.
Last edited on
Without seeing the data, let's say the .dat file looks something like this:

john doe
+5 implant
10
5
5000000

Then, the overload would look something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Contract operator>>(istream in, Contract& c)
    {
		string tmp;
		int tmp2, tmp3;
		
		getline(in, c.name);
		getline(in, tmp);
		getline(in, tmp2);
		getline(in, tmp3);
		getline(in, c.totalPrice);

		c.items.push_back(tmp);
		c.amount.push_back(tmp2);
		c.amountObtained.push_back(tmp3);
     } 


Keep in mind, the above is probably terribly wrong (in most ways it can be - I'm fairly new to this myself). However, it's a good starting point.

Once the function is complete, dataIn >> temp should function as I believe you intended it to.
Last edited on
As for what's going on..

When the compiler see's "dataIn >> temp", you're telling it that you want to input something from the file dataIn into the object temp. However, since temp is currently using the standard definition of the instream operator (>>), it has absolutely no idea what to do with the data it's seeing.

By overloading the operator, you're telling the compiler, "hey, I need this data to go into this object in this particular way". Using that information, the compiler (and the object) know what you want and how to do it. Otherwise, to the compiler, it makes about as much sense as cin>>int.
It might help to know what the program is going to do.
I'm trying to write something that will allow the user to create contracts and save them so they can close out of the program and when they open it again, it will load the contracts from the .dat file. I have no idea if I'm going at this the right way, but all the tutorials I found deal with integers and strings and whatnot, but it's really the only way I know how to do this. So I want it to save each contract object and then when the program starts, it looks to see if there are any contracts in the data file and imports them into the program. Does this help?

@Thrax
Thank you, but the member vars of the object are vectors, which may need a different tactic... Also, your explanation was very clear for me, which I appreciate.
The getline() commands above should deal with vectors just fine. It stores the data in a tmp variable, then inserts it into the end of the vector after all data has been extracted.

Alternately, you could still extract the data in the way mentioned above - but instead of dealing with the private members directly (which you probably won't have permission to do since they are private), you can pass the tmp variables to some function that will deal with them properly.

LowestOne brings up a good point though. If the .dat file isn't ready to read (isn't parsed, compressed, encrypted), then this effort may be all for not.
I actually need getline() to work with my contract objects. I'm assuming that's what the overloaded function was for...
But you have a .dat, which is most likely not human readable. If you open it up with Notepade and see something like:

¶aòŒ¯óßžòõ: Øé+OW§Ã

then you have a problem with your whole approach.

You have to open your file: inFile.open("name", ios::in | ios::binary);
Then to read something you use inFile.read( *char, amountToBeRead)
Even reading an integer, called i inFile.read(reinterpret_cast<char*>&i, sizeof(i))

So something like this:

john doe
+5 implant
10
5
5000000

Becomes a little tricky. There is probably an integer (but perhaps a short or maybe a char, which is a byte) before "john doe", which will tell you how long that string is.

+5 would make one assume that this value is signed. Again, probably a flag to how long the "implant" string is.

Their might be a header to the file, which you would need to maintain, and perhaps a count of how many contracts there are. Then maybe data at the end of the file too.

And then hopefully it isn't compressed and/or protected.



Last edited on
If the .dat file isn't ready to read (isn't parsed, compressed, encrypted), then this effort may be all for not.

Yeah that is what I was getting at. Most the games I play encrypt game sensitive things like that. I would imagine a file that has your quest info on it would definitely be game sensitive and encrypted or compressed in some way.
Oooookay. Using .dat files is waaay over my head. If I used a .txt, would it work better? Could I still store objects in an text file? Sorry about all of this, this is just my first time working with saving data...
Wait, is the dat file from the MMO or is it one you created? The way you have been talking it is from the MMO. The fastest way to find if the dat file is encrypted or not is to open in a text editor. If the file has text that is readable from start to end then it is a simple text file they named *.dat. If it comes up with tons of letters, symbols, and numbers then it is encrypted or compressed. If it is a file you made then it will be purely text til you learn how to encrypt it or compress it and do so. Which MMO are we talking about here anyways? WoW, Last Chaos, Guild Wars, etc?
It's one I created. Sorry for the misunderstanding. I'm making this for a clan in a remake of runescape as it was in 2006 (don't judge me! I love the nostalgia!).
Can't judge you, never played Runescape. If it is a file you are making then there is no encryption or compression. The dat file is simply a text file in that case and should be able to read it in fairly easily. We just got confused on what you were doing and gave advice according to what we had understood.
Pages: 12