reading and writing to binary files

R

Robert Reijntjes

Hi,

I need to read/write data from/to binary files that have an already
defined.
This means I can't define classes with the [Serializable] attribute.
The files also have arrays with variable length. This means I can't use
the StructLayout attribute like in here:
http://www.builderau.com.au/architect/webservices/0,39024590,20277904,00.htm


I came up with my own solution using reflection. I'm just starting with
programming in the .net environment so I'm a bit unsure if this
solution is any good. Can anyone tell if there are better solutions or
if I can improve on the current solution?

class SomeStruct
{
public char[] Version =new char[8];
public int a;
public int[] b;
}

private void Write()
{
SomeStruct strct = new SomeStruct();
strct.b = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
strct.Version = "test".ToCharArray();

FileStream fs = new FileStream(@"c:\temp\test.bin", FileMode.Create);
BinaryWriter w = new BinaryWriter(fs);

object o = WriteObject(strct, w);

w.Close();
fs.Close();
}

private void Read()
{
SomeStruct strct = new SomeStruct();
strct.b = new int[10];

FileStream fs = new FileStream(@"c:\temp\test.bin", FileMode.Open);
BinaryReader r = new BinaryReader(fs);

object o = ReadObject(strct, r);

r.Close();
fs.Close();
}

public static object ReadObject(object oObject,BinaryReader r)
{
string sFieldType;

Type tyObject = oObject.GetType();
FieldInfo[] miMembers = tyObject.GetFields();

foreach (FieldInfo info in miMembers)
{
if (info.FieldType.IsAssignableFrom(typeof(Int32)))
{
info.SetValue(oObject, r.ReadInt32());
}
else if (info.FieldType.IsAssignableFrom(typeof(Int32[])))
{
int[] tmp = (int[])info.GetValue(oObject);
int len = Buffer.ByteLength(tmp);
byte[] bts = r.ReadBytes(len);
Buffer.BlockCopy(bts, 0, tmp, 0, tmp.Length);
info.SetValue(oObject,tmp);
}
else if (info.FieldType.IsAssignableFrom(typeof(Char[])))
{
char[] tmp = (char[])info.GetValue(oObject);
tmp = r.ReadChars(tmp.Length);
info.SetValue(oObject, tmp);
}
}
return (oObject);
}

public static object WriteObject(object oObject,BinaryWriter w)
{
string sFieldType;

Type tyObject = oObject.GetType();
FieldInfo[] miMembers = tyObject.GetFields();

foreach (FieldInfo info in miMembers)
{
if (info.FieldType.IsAssignableFrom(typeof(Int32)))
{
w.Write((int)info.GetValue(oObject));
}
else if (info.FieldType.IsAssignableFrom(typeof(Int32[])))
{
int[] tmp = (int[])info.GetValue(oObject);
int len = Buffer.ByteLength( tmp );
byte[] bts= new byte[len];
Buffer.BlockCopy(tmp, 0, bts, 0, len);
w.Write(bts);
}
else if (info.FieldType.IsAssignableFrom(typeof(Char[])))
{
w.Write((char[])info.GetValue(oObject));
}
}
return (oObject);
}

Thanks,
Robert Reijntjes
 
T

the.duckman

I was actuly just working on a similar problem.

I used a single function to do the reading and writing, it took a
direction parabater (store or retrive). This ment that when writing a
function to say write all feilds of a class to disk I only had to write
the code one and then change the persitance direction for a load
operation.

Anyway sf.net has a few good .NET object persistance frameworks that
are allwrite[sic].

-dm



Robert said:
Hi,

I need to read/write data from/to binary files that have an already
defined.
This means I can't define classes with the [Serializable] attribute.
The files also have arrays with variable length. This means I can't use
the StructLayout attribute like in here:
http://www.builderau.com.au/architect/webservices/0,39024590,20277904,00.htm


I came up with my own solution using reflection. I'm just starting with
programming in the .net environment so I'm a bit unsure if this
solution is any good. Can anyone tell if there are better solutions or
if I can improve on the current solution?

class SomeStruct
{
public char[] Version =new char[8];
public int a;
public int[] b;
}

private void Write()
{
SomeStruct strct = new SomeStruct();
strct.b = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
strct.Version = "test".ToCharArray();

FileStream fs = new FileStream(@"c:\temp\test.bin", FileMode.Create);
BinaryWriter w = new BinaryWriter(fs);

object o = WriteObject(strct, w);

w.Close();
fs.Close();
}

private void Read()
{
SomeStruct strct = new SomeStruct();
strct.b = new int[10];

FileStream fs = new FileStream(@"c:\temp\test.bin", FileMode.Open);
BinaryReader r = new BinaryReader(fs);

object o = ReadObject(strct, r);

r.Close();
fs.Close();
}

public static object ReadObject(object oObject,BinaryReader r)
{
string sFieldType;

Type tyObject = oObject.GetType();
FieldInfo[] miMembers = tyObject.GetFields();

foreach (FieldInfo info in miMembers)
{
if (info.FieldType.IsAssignableFrom(typeof(Int32)))
{
info.SetValue(oObject, r.ReadInt32());
}
else if (info.FieldType.IsAssignableFrom(typeof(Int32[])))
{
int[] tmp = (int[])info.GetValue(oObject);
int len = Buffer.ByteLength(tmp);
byte[] bts = r.ReadBytes(len);
Buffer.BlockCopy(bts, 0, tmp, 0, tmp.Length);
info.SetValue(oObject,tmp);
}
else if (info.FieldType.IsAssignableFrom(typeof(Char[])))
{
char[] tmp = (char[])info.GetValue(oObject);
tmp = r.ReadChars(tmp.Length);
info.SetValue(oObject, tmp);
}
}
return (oObject);
}

public static object WriteObject(object oObject,BinaryWriter w)
{
string sFieldType;

Type tyObject = oObject.GetType();
FieldInfo[] miMembers = tyObject.GetFields();

foreach (FieldInfo info in miMembers)
{
if (info.FieldType.IsAssignableFrom(typeof(Int32)))
{
w.Write((int)info.GetValue(oObject));
}
else if (info.FieldType.IsAssignableFrom(typeof(Int32[])))
{
int[] tmp = (int[])info.GetValue(oObject);
int len = Buffer.ByteLength( tmp );
byte[] bts= new byte[len];
Buffer.BlockCopy(tmp, 0, bts, 0, len);
w.Write(bts);
}
else if (info.FieldType.IsAssignableFrom(typeof(Char[])))
{
w.Write((char[])info.GetValue(oObject));
}
}
return (oObject);
}

Thanks,
Robert Reijntjes
 
R

Robert Reijntjes

I was actuly just working on a similar problem.

I used a single function to do the reading and writing, it took a
direction parabater (store or retrive). This ment that when writing a
function to say write all feilds of a class to disk I only had to write
the code one and then change the persitance direction for a load
operation.

Anyway sf.net has a few good .NET object persistance frameworks that
are allwrite[sic].

-dm
The read and write functions share indeed a lot of functionality so I'll
try to turn them in to one function.

Thanks!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top