我有一个最大大小为1K的字节数组缓冲区。我想写出数组的一个子集(子集的开头总是元素0,但我们感兴趣的长度是变量)。
此处的应用程序是压缩。我将缓冲区传递给压缩函数。为简单起见,假设压缩将导致数据相等或小于1K字节。
byte[] buffer = new byte[1024];
while (true)
{
uncompressedData = GetNextUncompressedBlock();
int compressedLength = compress(buffer, uncompressedData);
// Here, compressedBuffer[0..compressedLength - 1] is what we're interested in
// There's a method now with signature Write(byte[] compressedData) that
// I won't be able to change. Short of allocating a custom sized buffer,
// and copying data into the custom sized buffer... is there any other
// technique I could use to only expose the data I want?
}
我真的想在这里避免复制 - 似乎完全没有必要,因为所有需要的数据都在buffer
中。
答案 0 :(得分:11)
Buffer.BlockCopy将是我的选择。
Microsoft示例:http://msdn.microsoft.com/en-us/library/system.buffer.blockcopy.aspx
const int INT_SIZE = 4;
int[] arr = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
Buffer.BlockCopy(arr, 3 * INT_SIZE, arr, 0 * INT_SIZE, 4 * INT_SIZE);
foreach (int value in arr)
Console.Write("{0} ", value);
// The example displays the following output:
// 8 10 12 14 10 12 14 16 18 20
您的代码如下:
uncompressedData = GetNextUncompressedBlock();
int compressedLength = compress(buffer, uncompressedData);
Buffer.BlockCopy(buffer, 0, buffer, 0, compressedLength);
答案 1 :(得分:6)
如果您无法更改方法签名,那么您就会陷入困境。您无法在类型为byte [] 的字节数组上创建“视图”。理想的解决方案是操作要么采用ArraySegment<byte>
或byte[]
,然后是偏移和计数。如果你真的无法改变Write方法,那么遗憾的是你不得不创建一个新数组并将数据复制到它。
答案 2 :(得分:3)
你无法做到这一点。 Array.Resize而不是更改数组的长度,只需将其复制到新的数组实例。
但是,您可以使用性能更佳的Buffer class:
Buffer提供了将字节从一个基本类型数组复制到另一个基本类型数组,从数组中获取一个字节,在数组中设置一个字节以及获取数组长度的方法。与System.Array类中的类似方法相比,此类为操作基元类型提供了更好的性能。
这符合您的需要,因为您有一个字节数组,而byte是基本类型。
答案 3 :(得分:3)
byte[] b = new Byte[] {1, 2, 3, 4, 5};
IEnumerable<Byte> middle = b.Skip(2).Take(3);
这应该让你得到你喜欢的任何中间部分。这很可能是副本,但我认为你不应该试图避免这种情况。
答案 4 :(得分:2)
如果方法签名为(byte[])
,则除了复制之外,您无法执行任何操作。
如果您可以更改签名:
stream支持编写数组的子集,因此请求Stream.Write之类的签名并不罕见:
public abstract void Write(
byte[] buffer,
int offset,
int count)
另一个选项是传递IEnumerable<byte>
,这样您就可以按照自己的方式切片,而无需复制。