7

我有一个最大大小为 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已经在里面了。

4

5 回答 5

12

Buffer.BlockCopy 将是我的选择。

微软示例: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);
于 2012-05-10T18:08:17.947 回答
6

如果您无法更改方法签名,那么您将陷入困境。您不能在类型为 byte[] 的字节数组上创建“视图” 。理想的解决方案是操作采用 anArraySegment<byte>或 abyte[]后跟偏移量和计数。如果您真的无法更改 Write 方法,那么不幸的是,您只能创建一个新数组并将数据复制到其中。

于 2012-05-10T18:01:30.727 回答
6
    byte[] b = new Byte[] {1, 2, 3, 4, 5};
    IEnumerable<Byte> middle = b.Skip(2).Take(3);

这应该让你得到你喜欢的任何中间部分。这很可能会复制,但我认为您不应该尝试避免这种情况。

于 2012-05-10T18:23:37.760 回答
3

你没有办法做到这一点。Array.Resize不是更改数组的长度,而是简单地将其复制到一个新的数组实例中。

但是,您可以使用Buffer 类,它具有更好的性能:

Buffer 提供了将字节从一个原始类型数组复制到另一个原始类型数组、从数组中获取字节、在数组中设置字节以及获取数组长度的方法。与 System.Array 类中的类似方法相比,此类为操作原始类型提供了更好的性能。

这符合您的需求,因为您有一个字节数组,而 byte 是一种原始类型。

于 2012-05-10T18:08:35.463 回答
2

如果方法签名是(byte[])你不能做任何事情,只能复制。

如果您可以更改签名:

  • 流支持写入数组的子集,因此具有类似Stream.Write的签名的请求并不罕见:

    public abstract void Write( byte[] buffer, int offset, int count)

  • 另一种选择是通过IEnumerable<byte>,这样您就可以在不复制的情况下以任何方式对数组进行切片。

于 2012-05-10T18:02:30.680 回答