TheDeveloperBlog.com


C# Dictionary Binary File

Dictionary binary file. A Dictionary can be stored in a binary file. This provides excellent performance. By combining FileStream, BinaryReader and BinaryWriter, we develop here a custom file format that allows for efficient persistence of a Dictionary.

BinaryWriterBinaryReader

Example. First we mention the file format. The binary file where the Dictionary is persisted contains a single 32-bit integer at the start. This tells us how many pairs are found in the rest of the file. Then, we simply can read in that many pairs.

Code description. We introduce here the Read, Write and Main methods. In Main, you are asked to either Write the Dictionary and its contents to the file, or Read in a Dictionary from that file.

Console.ReadLine

In Write, we use the using statement on a FileStream and BinaryWriter. We implement the simple file format described. In Read, we use a FileStream and BinaryReader and then loop through the required number of pairs.

C# program that reads and writes binary file for Dictionary

using System;
using System.Collections.Generic;
using System.IO;

class Program
{
    static void Main()
    {
	while (true)
	{
	    Console.WriteLine("1=Write, 2=Read");
	    string value = Console.ReadLine();
	    if (value == "1")
	    {
		var dictionary = new Dictionary<string, string>();
		dictionary["perls"] = "dot";
		dictionary["net"] = "perls";
		dictionary["dot"] = "net";
		Write(dictionary, "C:\\dictionary.bin");
	    }
	    else if (value == "2")
	    {
		var dictionary = Read("C:\\dictionary.bin");
		foreach (var pair in dictionary)
		{
		    Console.WriteLine(pair);
		}
	    }
	}
    }

    static void Write(Dictionary<string, string> dictionary, string file)
    {
	using (FileStream fs = File.OpenWrite(file))
	using (BinaryWriter writer = new BinaryWriter(fs))
	{
	    // Put count.
	    writer.Write(dictionary.Count);
	    // Write pairs.
	    foreach (var pair in dictionary)
	    {
		writer.Write(pair.Key);
		writer.Write(pair.Value);
	    }
	}
    }

    static Dictionary<string, string> Read(string file)
    {
	var result = new Dictionary<string, string>();
	using (FileStream fs = File.OpenRead(file))
	using (BinaryReader reader = new BinaryReader(fs))
	{
	    // Get count.
	    int count = reader.ReadInt32();
	    // Read in all pairs.
	    for (int i = 0; i < count; i++)
	    {
		string key = reader.ReadString();
		string value = reader.ReadString();
		result[key] = value;
	    }
	}
	return result;
    }
}

Output

1=Write, 2=Read
1
1=Write, 2=Read
2
[perls, dot]
[net, perls]
[dot, net]
1=Write, 2=Read

You can see the Dictionary was written to the file. The Dictionary instances are separate in Main. I checked the C:\dictionary.bin file that was used. The file was 32 bytes, which means the characters were encoded with one byte each.


Discussion. There are many advantages to using a custom binary format to persist a collection such as a Dictionary. For one, if you are using integers instead of strings, a binary format can be used to efficiently encode these.

Also: Performance reading in the file is good. It doesn't require much parsing. The reads are sequential and thus exploit the cache.

The above code is efficient. But it could be faster. In the Read method, you could use the count integer read in from the file as the capacity in the Dictionary constructor. This eliminates resizes to the Dictionary's structures.

Capacity Property

Note: Thanks to Paul Bright for suggesting an article that shows how to read and write a Dictionary to a binary file.


Summary. A Dictionary can be written to and read from a binary file. This can improve performance dramatically in some cases. We developed a simple file format that stores the number of pairs in the first integer in the binary file.

And: This solution could be adapted to more complex Dictionary types and optimized further.