Search code examples
c#dictionaryreadfilewritefile

populating a dictionary of objects, from objects written separately in a file C#


I made an example program in order to get this going so I can actualy learn how to use it and aply it in my actual project. In brief, my first try was writting the Person instance into the file, but I couldnt populate later a list with the different instances written (I only could see the first written, and the list had only 1 element). So I came up with saving the Person instance into a dictionary, writting the dictionary into the file, and then reading complete dictionary from file before adding a new element (Person instance), but I couldnt accomplish this either.

Let's say a I have a class Person

[Serializable]
public class  Person
{
    public string name, lname;
    public int age;

    public void newperson(string name,
              string lname,
              int age)
    {
        this.name = name;
        this.lname = lname;
        this.age = age;
    }
}

in my main class I have two methods (honestly stolen from here, thanks @Daniel Schroeder @deadlydog) to write and read from file, through binary format.

    Person nper = new Person(); //nper, an instance of Person
    Dictionary<string, Person> dict = new Dictionary<string, Person>();
    const string file = @"..\..\data.bin";

_

public static void WriteToBinaryFile<T>(string filePath, T objectToWrite, bool append = false)
    {
        using (Stream stream = File.Open(filePath, append ? FileMode.Append : FileMode.Create))
        {
            var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            binaryFormatter.Serialize(stream, objectToWrite);
        }
    }

_

public static T ReadFromBinaryFile<T>(string filePath)
{
    using (Stream stream = File.Open(filePath, FileMode.Open))
    {
        var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        return (T)binaryFormatter.Deserialize(stream);
    }
}

I kind of understand this methods, but, I would be unable to code/modify them, it exceeds my knowledge.

In order to test writting/reading I dragged a few textboxes and a button1

 private void button1_Click(object sender, EventArgs e)
    {
        //saving textboxes to Person instance 
        nper.newperson(textBox4.Text, textBox5.Text, Convert.ToInt16(textBox6.Text));

        //saving that object into a dictionary<string,Person> the key is the name, the object is the Person itself
        dict[nper.name] = nper;

        //Writting this dict
        WriteToBinaryFile(file, dict, true);
    }

Then, I dragged a few more separated textboxes to check the reading:

private void button2_Click(object sender, EventArgs e)
    {
        try
        {
            //read the file and save all into dict (is this working like I think it should? is dict, getting all the data from file?)
            dict = ReadFromBinaryFile<Dictionary<string,Person>>(file);


            //write into diferent textboxes the Person properties, for the key that matches with another text box that i fill manually to check
            textBox1.Text = dict[tbSearch.Text].name;
            textBox2.Text = dict[tbSearch.Text].lname;
            textBox3.Text = dict[tbSearch.Text].age.ToString();
        }
        catch (Exception ex) { MessageBox.Show(ex.ToString()); }

in button2_Click is dict getting all the data from file?

edit: Try and result: Let's say I fill the initial boxes with John, Doe, 40 click button1 then load another one, Clark, Kent, 50

If I write "John" in tbSearch I see full data of John (name, lastname and age) If I fill with "Clark" I get a dictionary error "the key given was not present in the dictionary"


Solution

  • Set append parameter = false in WriteToBinaryFile(file, dict, false).

    When first call of WriteToBinaryFile method executed BinaryFormatter write dictionary with one element, In second try write a dictionary with two element but appended to first write, So BinaryFormatter when try deserialize stream, read first section contains save dictionary with one key in first try (first button1 click).