c# - 大字节数组 - 在字节数组中存储长度有什么好处?
问题描述
问:在数组本身中存储大数组的长度有什么好处吗?
解释:
假设我们使用 System.IO.Compression 命名空间的 GZipStream 类来压缩一些大型二进制序列化对象。输出将是一些压缩字节数组的 Base64 字符串。在稍后的某个时间点,Base64 字符串被转换回字节数组,并且需要解压缩数据。
在压缩数据时,我们创建一个新的字节数组,其大小为压缩字节数组 + 4。在前 4 个字节中,我们存储压缩字节数组的长度/大小,然后将长度和数据块复制到新数组. 这个新数组被转换为 Base64 字符串。
在解压缩时,我们将 Base64 字符串转换为字节数组。现在我们可以使用 BitConverter 类提取实际压缩数据的长度,该类将从前 4 个字节中提取 Int32。然后,我们分配一个字节数组,其长度是我们从前 4 个字节中获得的长度,并让 Stream 将解压缩的字节写入字节数组。
我无法想象这样的事情实际上有什么好处。它增加了代码的复杂性,需要执行更多的操作。可读性也降低了。单独的 BlockCopy 操作应该消耗如此多的资源,这根本没有好处,对吧?
压缩示例代码:
byte[] buffer = new byte[0xffff] // Some large binary serialized object
// Compress in-memory.
using (var mem = new MemoryStream())
{
// The actual compression takes place here.
using (var zipStream = new GZipStream(mem, CompressionMode.Compress, true)) {
zipStream.Write(buffer, 0, buffer.Length);
}
// Store compressed byte data here.
var compressedData = new byte[mem.Length];
mem.Position = 0;
mem.Read(compressedData, 0, compressedData.Length);
/* Increase the size by 4 to accommadate for an Int32 that
** will store the total length of the compressed data. */
var zipBuffer = new byte[compressedData.Length + 4];
// Store length of compressedData array in the first 4 bytes.
Buffer.BlockCopy(compressedData, 0, zipBuffer, 4, compressedData.Length);
// Store the compressedData array after the first 4 bytes which store the length.
Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, zipBuffer, 0, 4);
return Convert.ToBase64String(zipBuffer);
}
解压示例代码:
byte[] zipBuffer = Convert.FromBase64String("some base64 string");
using (var inStream = new MemoryStream())
{
// The length of the array that was stored in the first 4 bytes.
int dataLength = BitConverter.ToInt32(zipBuffer, 0);
// Allocate array with specific size.
byte[] buffer = new byte[dataLength];
// Writer data to buffer array.
inStream.Write(zipBuffer, 4, zipBuffer.Length - 4);
inStream.Position = 0;
// Decompress data.
using (var zipStream = new GZipStream(inStream, CompressionMode.Decompress)) {
zipStream.Read(buffer, 0, buffer.Length);
}
... code
... code
... code
}
解决方案
您将问题标记为 C#,这意味着 .NET,因此问题无关紧要:
框架已经用数组存储了长度。这就是数组类对索引器进行完整性检查的方式。它如何防止托管代码中的溢出攻击。仅此一项帮助就值得任何轻微的低效率(请注意,JiT 实际上能够修剪大多数检查。例如,对于循环,它只会在每个循环中查看一次运行变量)。
您必须一直深入到非托管代码并处理裸指针才能摆脱它。但你为什么要?差异如此之小,它属于速度咆哮。如果它很重要,您可能会得到一个实时编程案例。从 .NET 开始是个坏主意。
推荐阅读
- android - Flutter web:如何以步进形式进行水平滚动?
- ios - 优雅的方式在 Swift Combine 中组合Latest,而不会丢失价值和不平衡的发布者
- html - CSS:背景图像有时会在移动设备上丢失
- php - 如何使用 htaccesss 而不是文件夹仅提供图像
- python - Python - 使用 MS Azure 训练自定义语音的 API
- subtotal - 小计 VBA 问题
- python - 在一条曲线中绘制两个返回的列表
- visual-studio - 如何在 Microsoft Visual Studio 中禁用滚动越过文件的底线?
- django - Django,模型过滤器和其他外键模型排序
- c# - 如何在 C# 中计算屏幕上任意位置的鼠标点击次数?