Today I ‘ll show you how to read and write struct file with C# language, write C# structure file is one of the techniques about I/O
After write struct into file, you will see format file same as below picture, The reader can’t read it well, because you write with struct file!
Okay now. Let’s start how to do it!
This is my demo GUI
I have one struct with 5 params from 1 to 5 include:
param1: (string)
param2: (int)
param3: (double)
param4: (datetime)
param5: (char)
Here is MyParams struct
public struct MyParams
{
public string par1;
public int par2;
public double par3;
public DateTime par4;
public char par5;
}
Next, create the structFile Class with init file, init structure use Marshal class
public class StructFile
{
private object _oStruct = null;
private System.Type _stuctureType = null;
private string _pathOfFile = null;
private FileStream _fs = null;
public StructFile(string szFile, System.Type type)
{
_pathOfFile = szFile;
_stuctureType = type;
}
private void LoadFileStream(FileMode FileMode, FileAccess FileAccess, FileShare FileShare)
{
if (_fs == null)
{
try
{
_fs = new FileStream(_pathOfFile, FileMode, FileAccess, FileShare);
}
catch (Exception ex)
{
throw ex;
}
}
}
public bool EOF //End of File
{
get
{
if (_fs != null)
{
if (_fs.Position >= _fs.Length)
Close();
}
return _fs == null;
}
}
private byte[] StructToByteArray()
{
try
{
// This function copys the structure data into a byte[]
// Set the buffer ot the correct size
byte[] buffer = new byte[Marshal.SizeOf(_oStruct)];
// Allocate the buffer to memory and pin it so that GC cannot use the space (Disable GC)
GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned);
// Copy the struct into int byte[] mem alloc
Marshal.StructureToPtr(_oStruct, h.AddrOfPinnedObject(), false);
// Allow GC Free. Because u use Marshal so GC will dont Free your memory until you call GC.Free
h.Free();
// return the byte[]
return buffer;
}
catch (Exception ex)
{
throw ex;
}
}
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;
}
}
public object GetStructureValue()
{
byte[] buffer = new byte[Marshal.SizeOf(_stuctureType)];
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(), _stuctureType);
handle.Free();
if (_fs.Position >= _fs.Length)
Close();
return oReturn;
}
catch (Exception ex)
{
throw ex;
}
}
public void Close() //Close the file stream
{
if (_fs != null)
{
_fs.Close();
_fs = null;
}
GC.Collect();
}
public void Open(FileMode FileMode, FileAccess FileAccess, FileShare FileShare)
{
LoadFileStream(FileMode, FileAccess, FileShare);
}
}
On Main Form
We use below btnCreateFile_Click function to write structure file
with _path is
_path = Path.Combine(Application.StartupPath, "file.dat");
private void btnCreateFile_Click(object sender, EventArgs e)
{
MyParams p = new MyParams();
try
{
p.par1 = txtpa1.Text;
p.par2 = Convert.ToInt32(txtpa2.Text);
p.par3 = Convert.ToDouble(txtpa3.Text);
p.par4 = dtpa4.Value;
p.par5 = Convert.ToChar(txtpa5.Text);
}
catch (Exception ex)
{
MessageBox.Show(this, "Invalid Data enteredrn" + ex.Message);
return;
}
try
{
StructFile sf = new StructFile(_path, typeof(MyParams));
sf.Open(System.IO.FileMode.Append, System.IO.FileAccess.Write, System.IO.FileShare.None);
sf.WriteStructure((object)p);
sf.Close();
MessageBox.Show(this, "Saved Succeed!");
}
catch (Exception ex)
{
MessageBox.Show(this, ex.Message);
}
}
We use btnViewBinaryRecord_Click function to read info from binary file
private void btnViewBinaryRecord_Click(object sender, EventArgs e)
{
MyParams p = new MyParams();
StructFile sfRead = new StructFile(_path, typeof(MyParams));
sfRead.Open(System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite);
p = (MyParams)sfRead.GetStructureValue();
string temp = p.par1 + Environment.NewLine;
temp += p.par2.ToString() + Environment.NewLine;
temp += p.par3.ToString() + Environment.NewLine;
temp += p.par4.ToShortDateString() + Environment.NewLine;
temp += p.par5.ToString();
MessageBox.Show(temp);
}
Or you can download my full source code from below link
If you have any questions or feedback, leave your comment, we can discuss about it!
Regards!
Zidane