反序列化非常大的图像文件

问题描述 投票:0回答:1

我从WebAPI接收图像集作为ImageData对象的列表,每个对象都包含一个字节数组。

    public class ImageData
    {
        public byte[] data;
    }

[当我有许多小尺寸图像时,我可以接收API响应并使用JObject将其反序列化,而不会出现任何问题。下面完美地工作。

using (var sr = new StreamReader(stream))
using (var jr = new JsonTextReader(sr))
{

 while (jr.Read())
 {
     if (jr.TokenType == JsonToken.StartObject)
     {
        imageData = JObject.Load(jr).ToObject<ImageData>();
     }
 }

}

但是,有时我只有一个非常大的图像文件(超过200MB)。在这种情况下,常规的反序列化方法不起作用。我不断收到OutOfMemory异常。

我尝试读取缓冲区中的响应并获取字节数组,但是所有读取字节的末尾大小始终大于实际图像大小。如果原始图像大小约为220MB,我相信由于编码,最终的结果约为295MB。因此,永远无法正确写入图像。以下是我如何缓冲阅读的内容。

byte[] buffer = new byte[1024];
List<byte[]> imageBytes = new List<byte[]>();

while (true)
{
    int read = stream.Read(buffer, 0, buffer.Length);
    if (read <= 0)
        break;  
    imageBytes.Add(buffer);
}

var output = new byte[imageBytes.Sum(arr => arr.Length)];
int writeIdx = 0;
foreach (var byteArr in imageBytes)
{
    byteArr.CopyTo(output, writeIdx);
    writeIdx += byteArr.Length;
}

imageData = new ImageData() { data = output };

我在这里想念什么?如何在没有内存异常或额外字节的情况下从巨大的有效负载中获取图像数据?

----更新---

我在下面尝试过,但仍然比原始字节大。

while (true)
{
    read = await stream.ReadAsync(buffer, 0, 1024);
    ++count;
    if (read <= 0)

    bytesRead += read;
    ms.Write(buffer, 0, read);
}

imageData = new ImageData() { data = ms.ToArray() };

[使用FileStream尝试过,temp.dcm大小再次约为290MB,而原始图像约为210MB:

string file = @"C:\Test\\temp.dcm";
using (FileStream fs = new FileStream(file, FileMode.Create, FileAccess.Write,
            FileShare.None, 4096, useAsync: true))
{
    await response.Content.CopyToAsync(fs);
}
c# json out-of-memory deserialization large-files
1个回答
0
投票

我认为以下代码更好,因为不确定是否可以消除该问题。最好使用Read方法的第3个参数指示最多要读取多少个字节,因此在一种情况下,首先可以将全部读取到buffer中,而在第二次仅读取几个字节中,因此可能会有一些剩余前Read个字节。 Kolay明胶。

while (true)
{
    Array.Clear(buffer, 0, buffer.Length);
    int read = stream.Read(buffer, 0, buffer.Length);
    if (read <= 0)
        break;  
    imageBytes.Add(buffer);
}
© www.soinside.com 2019 - 2024. All rights reserved.