【问题标题】:How to use Encoding.GetString with large amounts of data? (throws OutOfMemoryException)如何使用 Encoding.GetString 处理大量数据? (抛出 OutOfMemoryException)
【发布时间】:2013-01-11 07:51:30
【问题描述】:

我正在从 db 读取二进制数据并使用代码将其转换为文本。

       public String BinaryToText(byte[] data)
       {
         System.Text.Encoding encEncoder = System.Text.ASCIIEncoding.ASCII;

         return encEncoder.GetString(data);
       }

上述程序正常工作,但当二进制文件 >= 85mb 被转换时,OutOfMemoryException 如图所示。如何将大型二进制数据无误地转换成字符串。

【问题讨论】:

  • 你如何从文件中读取数据?
  • 不,我正在从 sqlserver 读取数据
  • 你似乎认为 ASCII 对“BinaryToText”就足够了……这是错误的,二进制的编码可以是任何编码。
  • @Esailija 好吧,它可能是对的;这在很大程度上取决于上下文。但是是的:它不太可能是正确的。通常我会期望 UTF-8 或 UTF-16(BE 或 LE)。但它可以是任何编码。或者没有。
  • @MarcGravell 它总是在某种编码中,没有没有编码之类的东西。但是使用 UTF-8 或 OS 代码页并没有什么害处,因为它们是 ASCII 超集……这可能就是为什么存在无编码混淆的原因……因为如此多的编码对 ASCII 字符进行编码与您可以拥有的主要字符完全相同编码搞砸了,而且从来没有注意到它,因为没有人使用过 ASCII 之外的字符,或者当 ASCII 不兼容的编码被引入搞砸组合时,你会注意到它。

标签: c# encoding out-of-memory


【解决方案1】:

除非您内存不足等情况,否则我通常不会认为 85MB 也有问题。即使 x86 通常也可以处理这个问题而无需暂停呼吸。

对于大量数据,最简单的答案始终是“不要一次将所有数据都保存在内存中”。 ADO.NET 在数据读取器上有一个只转发 API,它允许连续调用来获取大型 BLOB 的不同部分:

using(var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{  //                                    ^^ forwards-only mode ^^
  long offset = 0;
  int read;
  byte[] buffer = new byte[8096];
  while ((read = reader.GetBytes(colIndex, offset, buffer, 0, buffer.Length))>0)
  {
     ProcessBytes(buffer, 0, read);
     offset += read;
  }
}

其中ProcessBytes(byte[] buffer, int offset, int count) 处理来自buffercount 字节,从offset 开始。在 ASCII 的情况下,您可能完全可以不使用编码 ;对于其他编码,您可以使用Encoding.GetDecoder() API 来解码数据流,尽管它有点乱。这两件事一起将允许您处理任意大(必要时为数 TB)的数据源,而无需一次将其全部存储在内存中。

那么,下一个问题是:你打算用这些数据做什么

如果您确实需要一次将其全部存储在内存中,那么您别无选择,只能保留它。您可能可以使用迭代器块做一些事情,依次返回字符串的片段

【讨论】:

    猜你喜欢
    • 2021-12-16
    • 1970-01-01
    • 2022-11-25
    • 2015-12-17
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-24
    相关资源
    最近更新 更多