Reputation: 445
The array has duplicate elements and their order is important (must be kept). I have to save/load hundreds of these files constantly and each file may hold an array up to 100,000 elements.
The code bellow is an example of what I'm currently doing to save/load the files. Since IO is slow I got a significant speed improvement by casting the enums to byte before serialization (reducing the file size by 10x). I'm not sure I should be using BinaryFormatter though.
I'm still looking for improvements as everything should be as quick as possible, is there a better alternative to what I'm currently doing? How would you do it?
enum DogBreed : byte { Bulldog, Poodle, Beagle, Rottweiler, Chihuahua }
DogBreed[] myDogs = { DogBreed.Beagle, DogBreed.Poodle, DogBreed.Beagle, DogBreed.Bulldog };
public void Save(string path)
{
BinaryFormatter formatter = new BinaryFormatter();
FileStream stream = new FileStream(path, FileMode.Create);
byte[] myDogsInByte = Array.ConvertAll(myDogs, new Converter<DogBreed, byte>(DogBreedToByte));
formatter.Serialize(stream, myDogsInByte);
stream.Close();
}
public bool Load(string path)
{
if (!File.Exists(path))
{
return false;
}
BinaryFormatter formatter = new BinaryFormatter();
FileStream stream = new FileStream(path, FileMode.Open);
byte[] myDogsInByte = formatter.Deserialize(stream) as byte[];
myDogs = Array.ConvertAll(myDogsInByte, new Converter<byte, DogBreed>(ByteToDogBreed));
stream.Close();
return true;
}
private byte DogBreedToByte(DogBreed db)
{
return (byte)db;
}
private DogBreed ByteToDogBreed(byte bt)
{
return (DogBreed)bt;
}
EDIT: New code based on Jeremy suggestion, the code is working, I'll try to test the performance of it and post the results here as soon as I can.
enum DogBreed : byte { Bulldog, Poodle, Beagle, Rottweiler, Chihuahua }
DogBreed[] myDogs = { DogBreed.Beagle, DogBreed.Poodle, DogBreed.Beagle, DogBreed.Bulldog };
public void Save(string path)
{
byte[] myDogsInByte = new byte[myDogs.Length];
Array.Copy(myDogs,myDogsInByte,myDogs.Length);
File.WriteAllBytes(path, myDogsInByte);
}
public bool Load(string path)
{
if (!File.Exists(path))
{
return false;
}
byte[] myDogsInByte = File.ReadAllBytes(path);
myDogs = (DogBreed[])(object)myDogsInByte;
return true;
}
Upvotes: 1
Views: 332
Reputation: 11110
While the C# compiler will complain if you attempt to directly assign a byte[]
to an enum array. The runtime doesn't care.
var bytes = File.ReadAllBytes(path);
myDogs = (DogBreed[])(object)bytes;
The VS debugger will show that myDogs is really a byte array, but accessing an element from the array works just fine.
Update;
ArgumentException: Object must be an array of primitives.
So File.WriteAllBytes()
doesn't like being tricked with an enum[]
. You should be able to to use Array.Copy
to quickly duplicate the enum values into a byte[]
.
var buffer = new byte[myDogs.Length];
Array.Copy(myDogs, buffer, myDogs.Length);
File.WriteAllBytes(path, buffer);
Of course that's not a free operation, but it should be fairly fast even for large arrays.
Upvotes: 2