BinaryWriter and BinaryReader
What They Are, When to Use Them and How to Use Them
What They Are
BinaryWriter and BinaryReader are .NET classes that act as wrappers around a stream (like a FileStream or MemoryStream). Their purpose is to read and write primitive data types (int, double, bool, string, etc.) in a compact, non-human-readable binary format.
BinaryWriterconverts data types into their raw byte representations and writes them to the underlying stream.BinaryReaderreads raw bytes from a stream and converts them back into their original data types.
When to Use Them
Use BinaryWriter and BinaryReader when your priority is performance and file size, and the data does not need to be read by a human in a text editor.
Compact File Size 💾: Storing data in its binary form is much smaller than its text representation. For example, the number
1000000is 7 characters as a string but only 4 bytes as a binaryint.High Performance 🚀: Reading and writing binary data is faster than parsing text-based formats like JSON or XML because there is no complex parsing or text conversion involved.
Fixed Data Structures: They are perfect for creating custom file formats with a strict structure, such as application settings, game save files, or network data packets.
How to Use Them
The core principle is to read the data in the exact same order and type as it was written.
C# Example
This example writes an ID, a username, and a score to a binary file and then reads it back.
string filePath = "player.dat";
// --- Writing Data with BinaryWriter ---
try
{
using (var writer = new BinaryWriter(File.Open(filePath, FileMode.Create)))
{
// Write data in a specific order
writer.Write(101); // Player ID (int)
writer.Write("PlayerOne"); // Username (string)
writer.Write(9500.50); // Score (double)
writer.Write(true); // IsActive (bool)
}
Console.WriteLine("Data saved successfully.");
}
catch (IOException e)
{
Console.WriteLine($"Error writing file: {e.Message}");
}
// --- Reading Data with BinaryReader ---
try
{
using (var reader = new BinaryReader(File.Open(filePath, FileMode.Open)))
{
// Read data in the EXACT same order and type
int id = reader.ReadInt32();
string username = reader.ReadString();
double score = reader.ReadDouble();
bool isActive = reader.ReadBoolean();
Console.WriteLine("\n--- Player Data ---");
Console.WriteLine($"ID: {id}");
Console.WriteLine($"Username: {username}");
Console.WriteLine($"Score: {score}");
Console.WriteLine($"Is Active: {isActive}");
}
}
catch (IOException e)
{
Console.WriteLine($"Error reading file: {e.Message}");
}
Key Concerns and Considerations
Strict Order is Crucial ⚠️: The biggest concern is that you must read the data in the identical sequence and with the correct data types it was written. Reading an
intwhere adoublewas written will result in corrupted data and likely throw an exception. The file itself has no metadata to describe its structure.Not Human-Readable: The output files (
.bin,.dat, etc.) are binary and will look like gibberish if opened in a standard text editor. This makes manual inspection and debugging difficult.Cross-Platform Portability (Endianness): By default,
BinaryWriteruses little-endian byte order. If you share binary files with a system that uses big-endian order (like some older hardware or network protocols), the multi-byte values (int,double, etc.) will be misinterpreted. This is an advanced concern but critical for cross-platform applications.Write(string)Format:BinaryWriter.Write(string)uses a specific format called a length-prefixed string. It first writes the length of the string as a compact integer, then writes the string's character bytes.BinaryReader.ReadString()expects this format. You cannot use it to read a string from a plain text file.