Click to See Complete Forum and Search --> : saving a structure as binary


stevendo
August 29th, 2008, 10:09 PM
so i was wondering how exactly do i go about saving a structure a a bionary format

say in c i have


struct mystructre {

int number;
char mystring [50];

};

...save the structure as binary...


how would i do this in C# with a string as the char array?

darwen
August 30th, 2008, 01:47 AM
Hello. Please use code tags - see link in my signature.

Try this :


[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
struct Example
{
public int number;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
public string message;
}


You can test this by doing :


Example example = new Example();
example.number = 100;
example.message = "hello";

byte[] data = new byte[Marshal.SizeOf(example)];
GCHandle dataPtr = GCHandle.Alloc(data, GCHandleType.Pinned);
Marshal.StructureToPtr(example, dataPtr.AddrOfPinnedObject(), false);

Example newExample = (Example)Marshal.PtrToStructure(dataPtr.AddrOfPinnedObject(), typeof(Example));
dataPtr.Free();

Console.WriteLine(string.Format("{0} {1}", newExample.number, newExample.message));


You can then use a BinaryWriter with a MemoryStream to write the structure to binary.

Darwen.

stevendo
August 30th, 2008, 11:06 AM
ok i understand all of this but do i write dataPtr or newexample to the file using the binary writer? is newExample simple showing how to read that data back in?

darwen
August 30th, 2008, 01:44 PM
If you looked at the members on BinaryWriter this should have been obvious, but anyway here's some more code

I write out the size of the byte array containing the struct before writing out the struct data, so that when reading back in I know how many bytes to read.


[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
struct Example
{
public int number;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
public string message;
}

class Program
{
static void SaveExample(Example example, string filename)
{
byte[] data = new byte[Marshal.SizeOf(example)];

// save the structure's data to the byte [] array 'data'
GCHandle dataPtr = GCHandle.Alloc(data, GCHandleType.Pinned);
Marshal.StructureToPtr(example, dataPtr.AddrOfPinnedObject(), false);
dataPtr.Free();

// save to a file
using (FileStream stream = new FileStream(filename, FileMode.Create))
{
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(data.Length); // write the length of the data first
writer.Write(data); // write the struct data
}
}

static Example LoadExample(string filename)
{
using (FileStream stream = new FileStream(filename, FileMode.Open))
{
BinaryReader reader = new BinaryReader(stream);

// get the length of the structure's data
int dataLength = reader.ReadInt32();

// read the structure's data
byte[] data = reader.ReadBytes(dataLength);

GCHandle dataPtr = GCHandle.Alloc(data, GCHandleType.Pinned);
Example example = (Example)Marshal.PtrToStructure(dataPtr.AddrOfPinnedObject(), typeof(Example));
dataPtr.Free();
return example;
}

}

static void Main(string[] args)
{
Example example = new Example();
example.number = 100;
example.message = "hello";

string filename = @"c:\test.dat";

SaveExample(example, filename);

Example newExample = LoadExample(filename);

Console.WriteLine("{0} {1}", newExample.number, newExample.message);
}
}

Talikag
August 30th, 2008, 03:04 PM
Isn't it possible to serialize a struct?
You can easily convert from bytes to binary...

darwen
August 30th, 2008, 04:25 PM
Isn't it possible to serialize a struct?
You can easily convert from bytes to binary...


If you're talking about the BinaryFormatter as detailed here ('http://msdn.microsoft.com/en-us/library/72hyey7b(VS.71).aspx') then this doesn't just put the struct data into the stream : it saves a considerable amount of extra information such as type, assembly credentials etc etc.

I'm presuming stevendo needs to save the same way as C++ would save the structure.

Darwen.