C#将大型数组序列化为磁盘

时间:2010-10-05 12:56:06

标签: c# serialization large-files

我有一个非常大的图形存储在一个单维数组(大约1.1 GB)中,我可以将其存储在我的机器的内存中,该机器运行Windows XP,内存为2GB,虚拟内存为2GB。我能够在内存中生成整个数据集,但是当我尝试使用BinaryFormatter将其序列化到磁盘时,文件大小变为大约50MB,然后给我一个内存不足的异常。我用来编写代码的代码与我在所有较小的问题中使用的代码相同:

StateInformation[] diskReady = GenerateStateGraph();
BinaryFormatter bf = new BinaryFormatter();
using (Stream file = File.OpenWrite(@"C:\temp\states.dat"))
{
    bf.Serialize(file, diskReady);
}

搜索算法非常轻量级,我可以在此图表上执行搜索,一旦内存中没有问题。

我真的有3个问题:

  1. 有更可靠的方法吗? 将大型数据集写入磁盘。一世 猜你可以定义大到什么时候 数据集的大小接近 可用内存量, 虽然我不确定如何准确 就是这样。

  2. 我应该转移到更多数据库 中心方法?

  3. 有人能指点我吗? 关于阅读部分的文献 来自磁盘文件的大数据集 C#?

3 个答案:

答案 0 :(得分:1)

我对这类大量信息的体验是手动将其写入磁盘,而不是使用内置序列化。

这可能不是很实际,具体取决于您 StateInformation 类的复杂程度,但如果它非常简单,您可以使用BinaryReader和{手动编写/读取二进制数据{3}}而是。这些将允许您按照代码规定的预期预定顺序直接读取/写入大多数值类型。

此选项应该允许您快速读取/写入数据,但如果您希望稍后将信息添加到StateInformation中,或者要将其取出,因为您必须管理升级文件,这样做很麻烦

答案 1 :(得分:1)

自己编写条目。一个简单的解决方案就是:

StateInformation[] diskReady = GenerateStateGraph();
BinaryFormatter bf = new BinaryFormatter();
using (Stream file = File.OpenWrite(@"C:\temp\states.dat"))
{
  foreach(StateInformation si in diskReady)
    using(MemoryStream ms = new MemoryStream())
    {
      bf.Serialize(ms, diskReady);
      byte[] ser = ms.ToArray();
      int len = ser.Length;
      file.WriteByte((byte) len & 0x000000FF);
      file.WriteByte((byte) (len & 0x0000FF00) >> 8);
      file.WriteByte((byte) (len & 0x00FF0000) >> 16);
      file.WriteByte((byte) (len & 0x7F000000) >> 24);
      file.Write(ser, 0, len);
    }
}

一次只需要一个StateInformation对象的内存,并且反序列化你读取四个字节,构造长度,创建一个大小的缓冲区,填充它并反序列化。

如果您创建更专业的格式,上述所有内容都可以针对速度,内存使用和磁盘大小进行严格优化,但以上内容将说明原则。

答案 2 :(得分:0)

StateInformation中包含哪些内容?这是一堂课吗?结构

如果您只是担心易于使用的容器格式(可以轻松序列化到磁盘) - 创建一个类型化的DataSet,将信息存储到DataSet中,然后使用 WriteXml()方法DataSet将其持久保存到磁盘。然后,您可以创建空DataSet,然后使用 ReadXml()将内容加载回内存。

如果StateInformation位于具有值类型的结构中,则可以通过直接引用文件来查看MemoryMappedFile来存储/使用数组的内容,将其视为内存。这种方法比DataSet复杂得多,但它有自己的一套优势。