I am writing a simple program in C# to add, delete, change, and view key-value pairs. I would like to keep the dictionary used in this code inside a file. I want to load this dictionary from the file when starting the program, and on exit save the edited dictionary.
I have written both the code to write from the text file to the dictionary, and the code to write the dictionary to the text file on exit. Whenever I run the program with an empty text file it performs normally and adds any new entries to the dictionary. After exiting and saving these new dictionary key-values to the textfile, when I try to load the program again it seems that the key pair is already inside the dictionary and won't run the program.
My dictionary has nothing inside of it to start with as well.
The code to save the new dictionary into a text file is
private void btnExit_Click(object sender, EventArgs e)
{
File.WriteAllLines("myfile.txt",
names.Select(x => "[" x.Key "," x.Value "]").ToArray());
this.Close();
}
Which will make the output in the textfile in this format
[[email protected], Jack] [[email protected], Ashley] [[email protected], Sam]
The code to output the updated textfile to the dictionary is
private void Form1_Load(object sender, EventArgs e)
{
StreamReader sr = new StreamReader("myfile.txt");
string line;
while ((line = sr.ReadLine()) != null)
{
string[] arr = line.Split(',');
int i = 0;
while (i < arr.Length)
{
names.Add(arr[i], arr[i 1]);
i = 2;
}
}
}
CodePudding user response:
Instead of
names.Add(arr[i], arr[i 1]);
You can
names[arr[i]] = arr[i 1];
This second way just overwrites any existing entry in the dictionary with the new value, rather than crashing if the Key exists. You also have the option of using TryAdd which doesn't crash and doesn't add if the key exists. You can use the bool return value to work out whether the key/value added or not and if it didn't you can invoke some more complex logic such as merging the existing item with the one you wanted to add
One thing I can't work out about your question is that your code for writing surrounds the values with square brackets but the code for reading doesn't do anything with them and the sample file you posted doesn't contain them..
As a minor aside, there is also a File.ReadAllLines which is like File.WriteAllLines but the opposite direction; produces an array from a file. If you aren't wedded to CSV it might be a lot simpler to serialize to json - the most popular json serializer has help pages that shows how you might convert between an dictionary and a json string that you can write to a file in one go (File.WriteAllText) - help pages here: https://www.newtonsoft.com/json/help/html/serializedictionary.htm - I would have linked to an SO question but the canonical ones tend to have many variations on the theme (including ancient stuff like JavaScriptSerializer) - it essentially amounts to one line of code, plus another for writing:
var str = JsonConvert.SerializeObject(yourDictionary);
File.WriteAllText(path, str);
And reading it back would be something like:
var dict = JsonConvert.DeserializeObject<Dictionary<string,string>>(File.ReadAllText(path));
It's a really good wheel, that has already been invented and solves a lot of problems you might end up facing like your keys or values containing commas etc
CodePudding user response:
This will still give you problems if there's a comma in the key, but much less so than the original:
private void btnExit_Click(object sender, EventArgs e)
{
File.WriteAllLines("myfile.txt",
names.Select(x => $"{x.Key},{x.Value}"));
this.Close();
}
private void Form1_Load(object sender, EventArgs e)
{
var lines = File.ReadLines("myfile.txt");
foreach(var line in lines)
{
string[] arr = line.Split(',');
names.Add(arr[0], String.Join(",", arr.Skip(1)));
}
}
Even better to include a real CSV writer/parser and use that.