Hi guys I have a dictionary which has to be shared between two different exe files. The first application creates a key, then stores it in the dictionary, then the other application creates a key and stores it in the dictionary.
At the moment i do this:
private static void WriteToFile(Dictionary<string, byte[]> dictionary, string path)
{
Contract.Requires(dictionary != null);
Contract.Requires(!string.IsNullOrEmpty(path));
if (!(timestamp == File.GetLastWriteTime(DatabasePath)))
{
using (FileStream fs = File.OpenWrite(path))
using (var 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);
}
timestamp = DateTime.Now;
File.SetLastWriteTime(DatabasePath, timestamp);
}
}
}
/// <summary>
/// This is used to read a dictionary from a file
/// http://www.dotnetperls.com/dictionary-binary
/// </summary>
/// <param name="path">The path to the file</param>
/// <returns>The dictionary read from the file</returns>
private static Dictionary<string, byte[]> ReadFromFile(string path)
{
Contract.Requires(!string.IsNullOrEmpty(path));
var result = new Dictionary<string, byte[]>();
using (FileStream fs = File.OpenRead(path))
using (var reader = new BinaryReader(fs))
{
// Determine the amount of key value pairs to read.
int count = reader.ReadInt32();
// Read in all the pairs.
for (int i = 0; i < count; i++)
{
string key = reader.ReadString();
//// The byte value is hardcoded as the keysize is consistent
byte[] value = reader.ReadBytes(513);
result[key] = value;
}
}
return result;
}
Then when I want to store a key I call this method:
public static bool StoreKey(byte[] publicKey, string uniqueIdentifier)
{
Contract.Requires(ValidPublicKeyBlob(publicKey));
Contract.Requires(publicKey != null);
Contract.Requires(uniqueIdentifier != null);
Contract.Requires(uniqueIdentifier != string.Empty);
bool success = false;
if (File.Exists(DatabasePath))
{
keyCollection = ReadFromFile(DatabasePath);
}
if (!keyCollection.ContainsKey(uniqueIdentifier))
{
if (!keyCollection.ContainsValue(publicKey))
{
keyCollection.Add(uniqueIdentifier, publicKey);
success = true;
WriteToFile(keyCollection, DatabasePath);
}
}
return success;
}
When the programs generates the key and when we then try to access them, it only has 1 key, what am I doing wrong? The key and string is stored perfectly, but I’m just afraid that they are overwriting the files or something.
Thank you very much in advance, any help is greatly appreciated
PS: The databasePath is the path where I want to save the file, created as a field.
It is hard to say what exactly going on since you’ve not provided an information regarding how many items in dictionary and so on, but it seems like you’ve encountered some kind of a file access issue when accessing the same file from multiple processes.
You can use named Mutex as a cross process synchronization object so before accessing a file you have to ensure that Mutex handle is released so you can aquire an ownership and an other process would be able to wait before accessing a file.
EDIT: New finding
Also you trying to write immediately after the read, so perhaps FileSystem operation is not completed yet so write failed, I’m not sure 100% in this perhaps .NET managed classes like File/StreamReader/etc already handled such cases but I believe it worth to double check in your case since is not 100% clear what is happened. So just try out adding some timeout like
Thread.Sleep(500)between read and write operations.EDIT: One more thing you can do is download Process Monitor SysInternals utility and see which operations are failed when accessign a given file. So just add a new filter
Path=file nameand you would be able see what is going on on the low level.