了解字节数组的大小

Understanding the Size of Byte Arrays

我正在阅读这个流行的堆栈溢出问题 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, 0, buffer.Length)) > 0)
                {
                    ms.Write(buffer, 0, read);
                }

                return ms.ToArray();
            }

以下是我不理解的地方:

我对这个数组设置的大小感到困惑。例如,我使用该代码块将图像流转换为字节数组,但我通常读取大于 2 兆字节的图像,这远远大于图片中读取的数组大小 - 16* 1024 字节。但是,上面的代码完全可以将图像从流转换为字节数组,不会出现“越界索引”错误。

为什么我的阵列比我正在阅读的照片更小,但仍然能够完全正常地读取它?

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

您会注意到 ToArray 生成的数组比您的缓冲区大小大得多。

正如评论中已经提到的那样。 Picture stream的read函数只读取了一块数据, 实际上正是传输缓冲区的数量。 我们读取这个数量,然后将其写入传输缓冲区的输出流。

我试着写了一些代码来演示发生了什么:

    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, 0, transportBufferSizeInByte);

        //we write what we got to the output
        if(tempReadAmountInByte>0)
        {
            outPutMemoryStream.Write(transportBufferFor, 0, 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# 实现的行为相似。

查看有关此主题的一些 Q/A: [问题]: