Introduction
I have always found that when transporting data via files, one of the best methods is to store that data into a structure and then read it out in that structure again. Two of the main reasons for this would be: No one can read the data out the files without the structure and if you are transporting that data via TCP/IP, the traffic is reduced as the files are "compressed".
You could even use a binary file as a very simple data store when you have a small task to perform and do not want to transport your application with a database.
Description
The source file is basically one class which you can plug and play into any project.
The Constructor
The constructor of the class accepts the file name and a type. This is the struct
type. i.e.: If you had a struct
:
public struct MyStruct
{
public int i;
public string sz;
}
Then the type passed into the constructor would be the type of the struct
, i.e.:
StructFile structfile = new StructFile(@"c:\test.dat", typeof(MyStruct));
...
public StructFile(string szFile, System.Type type)
{
_File = szFile;
_oType = type;
}
To use the class after it has been initialized, you need to call Open
to open the files. This is a wrapper for the FileStream
object and accepts the same parameters.
As the class had to be generic enough to cater to all structures, it is internally an object type.
Writing the Struct to the File
public bool WriteStructure(object oStruct)
{
_oStruct = oStruct;
try
{
byte[] buf = StructToByteArray();
BinaryWriter bw = new BinaryWriter(_fs);
bw.Write(buf);
bw.Close();
bw = null;
return true;
}
catch (Exception ex)
{
throw ex;
}
}
private byte[] StructToByteArray()
{
try
{
byte[] buffer = new byte[Marshal.SizeOf(_oStruct)];
GCHandle h = GCHandle.Alloc(buffer , GCHandleType.Pinned);
Marshal.StructureToPtr(_oStruct, h.AddrOfPinnedObject(), false);
h.Free();
return buffer;
}
catch (Exception ex)
{
throw ex;
}
}
The structure is passed into the WriteStructure
function as an object. The object is then converted to a byte[]
which binarywriter
can use to print the data.
Reading the Data Back
public object GetNextStructureValue()
{
byte[] buffer = new byte [Marshal.SizeOf(_oType)];
object oReturn = null;
try
{
if (EOF) return null;
_fs.Read(buffer, 0, buffer.Length);
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
oReturn = (object)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
_oType);
handle.Free();
if (_fs.Position >= _fs.Length)
Close();
return oReturn;
}
catch (Exception ex)
{
throw ex;
}
}
Always remember to close the file once you are finished with it. :)
History
- 10th August, 2005: Initial post