【问题标题】:Read from a huge MemoryStream in C#从 C# 中的巨大 MemoryStream 中读取
【发布时间】:2011-04-08 17:56:25
【问题描述】:

我使用 BinaryReader (MemoryStream(MyByteArray)) 读取可变大小的记录并在内存中处理它们。只要我在数组中的字节流的大小小于 1.7 GB,这就会很好地工作。之后(这是我的 64 位系统中整数的最大大小),尽管我有足够的实际内存,但您无法创建更大的字节数组。所以我的解决方案是读取字节流并将其拆分为几个字节数组。

但是,现在我无法“读取”字节数组边界,而且由于我的数据是可变格式,我无法确保字节数组总是在整条记录上完成。

对于处理非常大的数据集并且仍然需要速度的人来说,这一定是一个常见问题。

我该如何处理这个问题?

【问题讨论】:

  • 你应该防止这个大小的字节数组被加载到内存中。是否可以实现一个流式解决方案,您只将数组的一部分加载到内存(缓冲区)中?你需要随机访问这些字节吗?或者您是否可以使用仅向前的解决方案,您可以在处理流时从头到尾读取流(并且不回头)。这个字节数组来自哪里?一个文件,一个网络服务,...?

标签: c# bytearray memorystream


【解决方案1】:

编辑:阅读基础知识后,我意识到内存映射文件可能比顺序访问的普通 I/O 慢。

你有没有尝试过这样的事情:

var stream = new FileStream("data", 
    FileMode.Open, 
    FileAccess.Read, 
    FileShare.Read, 
    16 * 1024, 
    FileOptions.SequentialScan)

var reader = new BinaryReader(stream);

如果您的数据位于文件中并且您可以使用 .NET 4.0,请考虑使用 MemoryMappedFile

然后您可以使用MemoryMappedViewStream 获取流或使用MemoryMappedViewAccessor 获取类似BinaryReader 的接口。

【讨论】:

  • 是的。我试过了 - 不幸的是 MemoryMappedFiles 确实很慢。
【解决方案2】:

对于过大的流,您不应该尝试将其转储到MemoryStream - 而是使用FileStream 之类的东西,并直接与磁盘通信。内置缓冲通常就足够了,或者您可以使用 BufferedStream 之类的东西来调整它(但我很少需要 - 但是我倾向于包含我自己的数据处理缓冲区)。

您还可以考虑压缩或密集打包数据,以及旨在通过流式传输记录而不是一次创建整个图表的序列化程序(尽管由于您提到BinaryReader,您可能已经高度手动执行此操作,因此这可能不是问题)。

【讨论】:

  • 是的。它被压缩 - wuite 有效,我用我自己的逻辑反序列化它。但是从磁盘读取太慢了。全部 - 我对这个巨大的数据文件使用并行处理并将它放在磁盘上会引起各种争用。
  • 使用 memoryStrea,全部在内存中 - 非常适合我 - 除了现在我的数据已经超出了字节数组的这个任意最大大小。
  • 我希望你先读完你的 300 封电子邮件,否则没有甜点 (SO) 适合你!
  • @ManInMoon - 然后(并考虑到您对内存映射文件的评论)您必须将数据拆分为多个字节数组,并编写您自己的内存支持流实现,或在允许多个独立内存流的合适点拆分它。
  • @MrWuf 取决于大小,真的;您应该能够按块顺序访问映射文件,而不必将很大一部分加载到内存流中;由你决定
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-13
  • 2019-02-19
  • 2012-06-04
相关资源
最近更新 更多