了解字节数组的大小

问题描述

我正在阅读这个流行的堆栈溢出问题Creating a byte array from a stream,想澄清一下字节数组的工作原理。

在这段代码中:

 byte[] buffer = new byte[16 * 1024];
            using (MemoryStream ms = new MemoryStream())
            {
                int read;
                while ((read = PictureStream.Read(buffer,buffer.Length)) > 0)
                {
                    ms.Write(buffer,read);
                }

                return ms.ToArray();
            }

这是我不了解的内容:

我迷失了这个数组的大小。例如,我使用该代码块将图像流转换为字节数组,但是我通常读取的图像大于2兆字节,这远大于图片中读取的数组的大小16 * 1024个字节。但是,以上代码将图像从流完全转换为字节数组,没有“越界索引”错误。

那么我的数组比我正在阅读的照片要小得多,但是仍然可以很好地读取它吗?

解决方法

您传递的数组只是一个缓冲区。当您从流中读取数据时,它返回读取的字节数,并用那么多元素填充缓冲区数组(它并不总是被完全填充)。然后,您将那么多字节写入内存流。重复此过程,直到没有更多字节要从文件中读取为止。

您会注意到ToArray产生的数组远大于缓冲区的大小。

,

正如评论中已经提到的。 读取图片流的功能仅读取大块数据, 实际上恰好是传输缓冲区的数量。 我们读取了这个数量后,便将其写入传输缓冲区的输出流中。

我试图编写一些代码片段以演示发生的情况:

    int inputBufferSizeInByte = 1024 * 1000 * 5;  // 5 MiB = 5000 KiB
    //                    AmountKiloByte * factor MiB * factorWhatWeWant
    Byte[] inputBuffer = new Byte[inputBufferSizeInByte];
    //we fill our inputBuffer with random numbers
    Random rnd = new Random();
    rnd.NextBytes(inputBuffer);

    //we define our streams
    MemoryStream inputMemoryStream = new MemoryStream(inputBuffer);
    MemoryStream outPutMemoryStream = new MemoryStream();

    //we define a smaller buffer for reading
    int transportBufferSizeInByte = 1024 * 16; // 16 KiB
    byte[] transportBufferFor = new byte[transportBufferSizeInByte]; 

    int amountTotalWeReadInByte = 0;
    int tempReadAmountInByte = 0;
    int callWriteCounter = 0;
    do
    {
        tempReadAmountInByte = inputMemoryStream.Read(transportBufferFor,transportBufferSizeInByte);

        //we write what we got to the output
        if(tempReadAmountInByte>0)
        {
            outPutMemoryStream.Write(transportBufferFor,tempReadAmountInByte);
            callWriteCounter++;
        }

        //we calc how the total amout
        amountTotalWeReadInByte += tempReadAmountInByte;

    } while (tempReadAmountInByte > 0);

    //we sum up 
    Console.WriteLine("input buffer size:   \t" + inputBufferSizeInByte + " \t in Byte");
    Console.WriteLine("total amount read   \t" + amountTotalWeReadInByte  + " \t in Byte");
    Console.WriteLine("output stream size: \t" + outPutMemoryStream.Length + " \t in Byte");
    Console.WriteLine("called strean write \t" + callWriteCounter + "\t\t times");

输出:

input buffer size:      5120000      in Byte
total amount read       5120000      in Byte
output stream size:     5120000      in Byte
called strean write     313      times

因此,我们调用313次流写入函数,一切都会按其应有的方式进行。

这使我想到了关键问题:

为什么内存中的图片和硬盘中的图片之间存在尺寸差异?

我确实认为图片编码是原因。

图片在硬盘上的大小与其内存表示形式的差异通常属于 图片编码。我从使用cpp库opencv知道这一事实。 我宁愿猜测C#实现的行为也类似。

查看有关此主题的一些问题: [问题]:JPEG image memory byte size from OpenCV imread doesn't seem right

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...