了解字节数组的大小
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:
[问题]:
我正在阅读这个流行的堆栈溢出问题 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:
[问题]: