读取二进制文件时避免LOH

时间:2013-04-03 07:39:00

标签: c# memory-management io large-object-heap

这个问题是一个跟进 Efficient way to transfer many binary files into SQL Server database

我最初问过为什么使用File.ReadAllBytes导致快速内存使用,并且使用该方法得出的结论是将数据放在大对象堆上,这在运行时期间无法轻易回收。

我现在的问题是如何避免这种情况?

using (var fs = new FileStream(path, FileMode.Open))
{
    using (var ms = new MemoryStream())
    {
        byte[] buffer = new byte[2048];
        int bytesRead;
        while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
        {
            ms.Write(buffer, 0, bytesRead);
        }
        return new CustomFile { FileValue = ms.ToArray() };
   }
}

以下代码旨在通过以块的形式而不是一次性读取文件来解决问题,但似乎存在同样的问题。

1 个答案:

答案 0 :(得分:2)

内存流包含整个数据的内部数组(最后返回)。只要你保持连接到内存流,你读取2048字节的块是没关系的。如果需要将数据作为包含整个文件的数组返回,那么最终通常会将该数组创建为大对象堆。

如果目标(BLOB字段或类似字段)不允许您以单字节数组之外的任何其他方式传入数据,那么您无法绕过分配包含所有数据的字节数组。 / p>

将数据传输到目标的最佳方式当然是目标也支持流语义。

int Transfer(Stream source, Stream target)
{
   byte buffer = new byte[BufSize];
   int totalBytesTransferred = 0;
   while ((bytesRead = source.Read(buffer, 0, BufSize)) > 0)
   {
      target.Write(buffer, 0, bytesRead);
      totalBytesTransferred += bytesRead;       
   }
   return totalBytesTransferred;
}

如果可能,取决于目标(例如,数据库BLOB)是否支持打开目标流。