Archived

This topic is now archived and is closed to further replies.

elis-cool

Data Structure File I/O

Recommended Posts

OK so I have a Linked List and what I want to do is save each of the nodes (as they hold their own data) into the same file, how would I go about this, and also load them back into nodes when the program is run again? via this method (possibly, unless you know better...): File.write((char*)this, sizeof(*this)); File.read((char*)this, sizeof(*this)); // inside member functions... CEO Plunder Studios

Share this post


Link to post
Share on other sites
Sounds good and basic.
But maybe for error-checking you should check into having a header or just an INT to tell you how many data items are included. At this stage it''s too early to worry about a compression scheme.

ZoomBoy
Developing a iso-tile 2D RPG with skills, weapons, and adventure. See my old Hex-Tile RPG GAME, character editor, diary, 3D Art resources at Check out my web-site

Share this post


Link to post
Share on other sites
Yeah but how do you write it so each node is stored after the last in the file sort of thing? and how do you load them back into the nodes correctly? since the nodes would have the *myNext pointer which would then be loaded into the nodes again and would be pointing to the wrong memory addresses...

CEO Plunder Studios

Share this post


Link to post
Share on other sites
Assuming your structs are declared something like this:

struct Link {
// data
char data[100];
Link *next;
};

If you know the size of ''data'', you can do:

Link *pLink = ...;
write(pLink->data, 100);

Another way [relies on ''next'' member being the last]:

Link *pLink = ...;
write(pLink, sizeof *pLink-sizeof pLink);

Or you could just write each ''Link'' data member individually:

write(pLink->data1, sizeof pLink->data1);
write(pLink->data2, sizeof pLink->data2);

Or you can use std::list:

  
std::list <Data> aList;
// fill aList

Data data = *aList.begin();
write(data, sizeof data);

Reverse this for reading.

Share this post


Link to post
Share on other sites
quote:
Original post by mongrelprogrammer
Don''t load (or save) the pointers to the next node... Just traverse the list saving the values then just incert them in order they are found in the file -> let the list rebuild itself.

- mongrelprogrammer

Well it holds more than one value... eg, strings, int''s, and they are of varing size''s...
At the moment everything is stored in the node class so I might make a seperate data class and when the program starts up add a new node to the list and have it point to the loaded Data class... any more ideas...



CEO Plunder Studios

Share this post


Link to post
Share on other sites
*Ahem*

You cannot arbitrarily save objects in binary format.

You can''t just use fwrite to save your data if your data objects contains pointers (you would just save the address, not the data, which would be completely useless), or if the data object has virtual functions (hence possibly a vtbl pointer), requires a constructor (which wouldn''t be called when restoring the object)...

In short, if it is not Plain Old Data (i.e. C structure), you will have to save your objects member by member (e.g. create an adequate ostream& operator<<( ostream& os, const Data&)


Assuming you have such an operator, you can just write, to save the data in ascii form


#include <list> // header for list
#include <iterator> // header for (i/o)stream_iterator
#include <algorithm> // header for copy
#include <fstream> // header for (i/o)fstream

using namespace std;

list theList;
ofstream ofs( "OutFile" ); // file stream to save
ifstream ifs( "InFile" ); // file stream to load

// save
copy( theList.begin(), theList.end(), ostream_iterator<Data>(ofs, '' '' ) );

// load
theList.assign( istream_iterator<Data>(ifs), istream_iterator<Data>() );


To save it in binary form, you will have to come up with your own function loading one object from a binary stream (similar to fread, but taking the object''s specificities into account) and combine it with algorithms like std::generate.

[Questions (STFW) | GDNet Start Here | GDNet Search | Forum FAQ | Google | Asking Smart Questions ]
[Docs (RTFM) | MSDN | SGI''s STL | OpenGL | File formats]
[C++ Must Haves (RTFS) | MinGW | Boost | Loki | FLTK | SDL ]

Stolen from Magmai Kai Holmlor, who held it from Oluseyi, who was inspired by Kylotan...

Share this post


Link to post
Share on other sites
Well I dont really want to write in text mode (possible sensitive info)...

But if I have to I could encrypt it... and have something like so saved to a file:
Start username
name
value
...
End
Start username
name
value
...
End
Or something and just read the file cheaking for the key word Start for where the next nodes data begins... this may be too slow for a large file...
Or I could just have a:

struct Data
{
string name;
int val;
...
};

and then have each node point to one of these that holds its data and just create a new node for each file it finds for the nodes and assign (ie. have a pointer) the Data to a new node...
but then if theres alot of nodes there may be way to many files in the directory...



CEO Plunder Studios

Share this post


Link to post
Share on other sites
quote:
Original post by elis-cool
Well I dont really want to write in text mode (possible sensitive info)...

But if I have to I could encrypt it... and have something like so saved to a file:
...


I don''t see how a binary file is any more secure that a text file.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Anything wrong with this??

struct Data
{
string str;
int value;
double anotherValue;
unsigned char byteCode;
};

struct Node
{
Data data;
Node* next;
Node()
{
next = NULL;
}
};

// Node* pTail = tail of list
Node* pTemp;
pTemp = pHead;

while(pTemp != NULL)
{
file.write((char*)&pTemp->data, sizeof(Data));
pTemp = pTemp->next;
}

file.close();


Might not compile right out of the box, consider it to be "pseudocode"..



Share this post


Link to post
Share on other sites
Yes, there''s something very wrong with that, which is to do with what Fruny has already said. Those strings will not be saved properly. You can''t use fwrite on strings.

[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions ]

Share this post


Link to post
Share on other sites
I didnt think you could as I had problems with it a few weeks ago...
Well a binary is a bit more secure as some random Joe bob cant just open the file in notepad and read everything, it would at least take someone trying to do it, to do it.
What if the Data class held a char name[] and put the string into that, that should work...
Well since this is a Database prog, how does GDnet store its info Dave?

CEO Plunder Studios

Share this post


Link to post
Share on other sites
Um, I have some struct''s with strings of varying length and they always get written and read just fine.

About saving the nodes, read and write the entire node and just be sure to give the pointer a new value(malloc or new) before using it(inserting it into the list).

Share this post


Link to post
Share on other sites
quote:
Original post by RolandofGilead
Um, I have some struct''s with strings of varying length and they always get written and read just fine.

Then it''s probably a POD struct.
quote:

About saving the nodes, read and write the entire node and just be sure to give the pointer a new value(malloc or new) before using it(inserting it into the list).

This technique is only adequate for POD types. It breaks as soon as you go beyond that.



[C++ FAQ Lite | ACCU | Boost | Python]

Share this post


Link to post
Share on other sites