1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Diagnostics;

namespace TestApp.UnitTests
{
    [TestFixture]
    // http://stackoverflow.com/questions/4021893/saving-a-dictionarystring-int32-in-c-serialization
    public class BinarySerializationTests
    {
        public interface IDictionarySerializer
        {
            void Serialize(Dictionary<string, int> dictionary, Stream stream);
            Dictionary<string, int> Deserialize(Stream stream);
        }

        public class BinaryDictionarySerializer : IDictionarySerializer
        {
            private BinaryFormatter formatter = new BinaryFormatter();

            public void Serialize(Dictionary<string, int> dictionary, Stream stream)
            {
                formatter.Serialize(stream, dictionary);
            }

            public Dictionary<string, int> Deserialize(Stream stream)
            {
                return (Dictionary<string, int>)formatter.Deserialize(stream);
            }
        }

        public class CustomBinaryDictionarySerializer : IDictionarySerializer
        {
            public void Serialize(Dictionary<string, int> dictionary, Stream stream)
            {
                BinaryWriter writer = new BinaryWriter(stream);
                writer.Write(dictionary.Count);
                foreach (var kvp in dictionary)
                {
                    writer.Write(kvp.Key);
                    writer.Write(kvp.Value);
                }
                writer.Flush();
            }

            public Dictionary<string, int> Deserialize(Stream stream)
            {
                BinaryReader reader = new BinaryReader(stream);
                int count = reader.ReadInt32();
                var dictionary = new Dictionary<string, int>(count);
                for (int n = 0; n < count; n++)
                {
                    var key = reader.ReadString();
                    var value = reader.ReadInt32();
                    dictionary.Add(key, value);
                }
                return dictionary;
            }
        }

        public class TextDictionarySerializer : IDictionarySerializer
        {

            public void Serialize(Dictionary<string, int> dictionary, Stream stream)
            {
                TextWriter writer = new StreamWriter(stream);
                foreach (var kvp in dictionary)
                {
                    writer.WriteLine("{0},{1}", kvp.Key, kvp.Value);
                }
                writer.Flush();
            }

            public Dictionary<string, int> Deserialize(Stream stream)
            {
                TextReader reader = new StreamReader(stream);
                var deserialized = new Dictionary<string, int>();
                string line;
                while (!String.IsNullOrEmpty(line = reader.ReadLine()))
                {
                    int commaIndex = line.LastIndexOf(',');
                    string key = line.Substring(0, commaIndex);
                    string value = line.Substring(commaIndex + 1);
                    deserialized.Add(key, int.Parse(value));
                }
                return deserialized;
            }
        }

        [Test]
        public void BinaryTest()
        {
            IDictionarySerializer serializer = new BinaryDictionarySerializer();
            TimeSerializeAndDeserialize(serializer);
        }

        [Test]
        public void TextTest()
        {
            IDictionarySerializer serializer = new TextDictionarySerializer();
            TimeSerializeAndDeserialize(serializer);
        }

        [Test]
        public void CustomBinaryTest()
        {
            IDictionarySerializer serializer = new CustomBinaryDictionarySerializer();
            TimeSerializeAndDeserialize(serializer);
        }

        private static void TimeSerializeAndDeserialize(IDictionarySerializer serializer)
        {
            MemoryStream stream = new MemoryStream(4 * 1048 * 1048);
            var dictionary = CreateTestDictionary();

            Stopwatch timer = new Stopwatch();
            long milliseconds = timer.Time(() => serializer.Serialize(dictionary, stream));
            Console.WriteLine("Serialize took {0}ms", milliseconds);
            stream.Position = 0;
            int count = 0;
            milliseconds = timer.Time(() => count = serializer.Deserialize(stream).Count);
            Assert.AreEqual(dictionary.Count, count);
            Console.WriteLine("Deserialize took {0}ms", milliseconds);
        }

        private static Dictionary<string, int> CreateTestDictionary()
        {
            var dictionary = new Dictionary<string, int>();
            for (int n = 0; n < 130000; n++)
            {
                dictionary.Add("Key " + n.ToString(), n * 2);
            }
            return dictionary;
        }
    }
}