【发布时间】:2020-06-02 03:53:59
【问题描述】:
数组有重复的元素,它们的顺序很重要(必须保持)。我必须不断地保存/加载数百个这样的文件,每个文件可能包含多达 100,000 个元素的数组。
下面的代码是我当前保存/加载文件的示例。由于 IO 很慢,我通过在序列化之前将枚举转换为字节(将文件大小减少 10 倍)显着提高了速度。我不确定我是否应该使用 BinaryFormatter。
我仍在寻求改进,因为一切都应该尽可能快,有没有比我目前正在做的更好的选择?你会怎么做?
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;
}
编辑:基于 Jeremy 建议的新代码,该代码正在运行,我将尝试测试它的性能并尽快在此处发布结果。
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;
}
【问题讨论】:
-
你绝对不应该使用
BinaryFormatter。只需像读取任何二进制文件一样读取字节,使用原始Stream,然后将读取的每个字节转换为枚举值。播放流的缓冲区大小以获得最佳性能。 -
您能否详细说明为什么这是最好的方法?我在其他地方读过有关使用 File.WriteAllBytes 和 File.ReadAllBytes 的信息。我对序列化性能几乎一无所知。
-
这个stackoverflow.com/a/30740756/4139809 建议你可以
myDogs = (DogBreed[])(object)myDogsInByte;? -
“对象必须是基元数组”。嗯,所以文件流不喜欢被
enum[]欺骗。所以你可以使用;var bytes = new byte[myDogs.Length]; Array.Copy(myDogs, bytes, myDogs.Length);从枚举复制到字节。 -
抱歉回复晚了,我根据您的建议更新了问题。将尝试衡量性能并稍后在此处发布。谢谢你的一切!
标签: c# optimization serialization