views:

103

answers:

4

I'm trying to read encrypted struct data from file using fread(). once i get the decrypted struct bytes, I'd like to it put them back into this struct.

struct data
{
  std::string s1;
  std::string s2;
  std::string s3;
  LONG l;
};

how would you convert a struct into bytes which can be reconstructed from bytes?

A: 

For the general case, write a function to serialize all members in the structure manually and another to create a structure from a byte stream by deserializing all members in order. You could use scripts to have these functions generated for you (sadly, C++ does not support stuff like Java's reflection).

You could take a look on boost/serialization.

Alexander Gessler
Convince me why this needed a downvote!
Joshua
For just one struct this is breaking a butterfly on a wheel, but I think it didn't deserve a downvote too, because he wrote "for the general case".
Axel Gneiting
+1  A: 

The problem is that std::string does not contain the bytes in question, it contains a pointer to the bytes you actually want to store. You should probably save each string as a null terminated string, and then save a raw long after that, in the file.

If you're looking for a "point and click" serialization solution like that provided by .NET, you will not find what you're looking for in C++. Boost's serialization library may be helpful because it will serialize some standard library objects for you, but you'll need your own implementation for a user defined class like that.

Billy ONeal
+1  A: 

I'd do something like:

struct serialized_data {
  size_t s1_offset;
  size_t s2_offset;
  size_t s3_offset;
  long l;
  char strings[1];
};

serialized_data* serialize (data d) {
    serialized_data* s = malloc(sizeof(serialized_data) + d.s1.length() + d.s2.length() + d.s3.length() + 3);
    s->s1_offset = 0;
    s->s2_offset = d.s1.length() + 1;
    s->s3_offset = s2_offset + d.s2.length() + 1;
    s->l = d.l;
    strcpy(s->strings, d.s1.c_str());
    strcpy(s->strings + s->s2_offset, d.s2.c_str());
    strcpy(s->strings + s->s3_offset, d.s3.c_str());

    return s;
}
sblom
Remember to handle the case where someone passes in garbage offsets/lengths in your deserialization code.
Billy ONeal
A: 
struct data 
{ 
  std::string s1; 
  std::string s2; 
  std::string s3; 
  long l; 
};


int Write(FILE* file, const data* myData)
{
   unsigned long length;

   length = myData->s1.size();
   fwrite((void*) &length, sizeof(length), 1, file);
   fwrite((void*) myData->s1.data(), length, 1, file);
   ... // write the other strings and long here
}

int Read(FILE* file, data* myData)
{
   unsigned long length;
   char* buffer;

   fread((void*) &length, sizeof(length), 1, file);
   buffer = new char[length];
   length = fread(&buffer, length, 1, file);
   myData.s1 = string(buffer, length);
}

Of course, do error checking and what not

Michael