-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Paul Hirch edited this page May 13, 2024
·
7 revisions
Grille.IO.BinaryView is a Libary to easily write and read binary data from streams and files.
Available as a NuGet Package.
In advance: this “documentation” is very sparse at the moment. I hope that most function and classes are self-explanatory enough. If you have any question or problems feel free to open an issue.
This library basically provides more advanced versions of the System.IO.BinaryWriter
and System.IO.BinaryReader
classes.
And has grown over the years to accommodate my custom file format (and occasionally reverse engineering) needs.
- Asymmetrical and Symmetrical write/read functions.
- Simple to use string functions with encoding options (including C-Strings).
- Convenient generic functions to serialize whole lists and (unmanaged) structs.
- Easy compresion/decompresion of sections or whole stream's with GZip, Deflate, Brotli or ZLib.
- Smart length prefixes depending on size. (42 takes 1 byte, 3000 takes 2 etc.)
- Support for byte endianness and bit order.
using Grille.IO;
using Grille.IO.Compression;
Write
// Open a file to write
using (var bw = new BinaryViewWriter("file.bin"))
{
// Type used for LengthPrefix by Strings and Arrays
bw.DefaultLengthPrefix = LengthPrefix.UInt32;
// Write data in the file
bw.WriteString(Name);
bw.WriteInt32(Age);
bw.Write<Vector2>(Pos);
// Compress section
bw.BeginCompressedSection(CompressionType.Deflate);
bw.WriteArray<byte>(Data0);
// Override default prefix to use byte instead
bw.WriteArray<Vector2>(Data1, LengthPrefix.Byte);
// Write length manuel
bw.WriteInt32(Data2.Length);
bw.WriteArray<float>(Data2, LengthPrefix.None);
bw.EndCompressedSection();
}
Read
// Open a file to read
using (var br = new BinaryViewReader("file.bin"))
{
br.DefaultLengthPrefix = LengthPrefix.UInt32;
// Read the data in same order of how they were written
Name = br.ReadString();
Age = br.ReadInt32();
Pos = br.Read<Vector2>()
// Decompress section
br.BeginCompressedSection(CompressionType.Deflate);
Data0 = br.ReadArray<byte>();
// Read prefix-type must match written one.
Data1 = br.ReadArray<Vector2>(LengthPrefix.Byte);
// Read length manuel
int length = br.ReadInt32();
Data2 = br.WriteArray<float>(length);
br.EndCompressedSection();
}
Uses same code for write and read operations.
using GGL.IO;
using GGL.IO.Compression;
View
// Open a file to read
using (var view = new BinaryView("file.bin", ViewMode.Read /*ViewMode.Write*/))
{
view.DefaultLengthPrefix = LengthPrefix.UInt32;
view.String(ref Name);
view.Int32(ref Age);
view.Struct<Vector2>(ref Pos);
view.BeginCompressedSection(CompressionType.Deflate);
view.Array<byte>(ref Data0);
view.Array<Vector2>(ref Data1, LengthPrefix.Byte);
// Switch when different operations are needed for read and write.
if (view.Mode == ViewMode.Read){
var br = view.Reader;
int length = br.ReadInt32();
Data2 = br.WriteArray<float>(length);
}
else {
var bw = view.Writer;
bw.WriteInt32(Data2.Length);
bw.WriteArray<float>(Data2, LengthPrefix.None);
}
// Above can also be solved this way:
/*
int length = Data2.Length;
view.Int32(ref length);
view.Array<float>(ref Data2, length);
*/
view.EndCompressedSection();
}