如何有效地获取C#中字节数组(前N个元素)的子集?

如何有效地获取C#中字节数组(前N个元素)的子集?,c#,.net,C#,.net,我有一个最大大小为1K的字节数组缓冲区。我想写出数组的一个子集(子集的开头总是元素0,但我们感兴趣的长度是一个变量) 这里的应用是压缩。我将缓冲区传递给压缩函数。为简单起见,假设压缩将产生相等或小于1K字节的数据 byte[] buffer = new byte[1024]; while (true) { uncompressedData = GetNextUncompressedBlock(); int compressedLength = compress(buffer, u

我有一个最大大小为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?
}

我真的希望避免在这里复制—它似乎完全没有必要,因为所需的所有数据都已经在
缓冲区中了。

如果您不能更改方法签名,那么您就卡住了。无法在byte[]类型的字节数组上创建“视图”。理想的解决方案是,该操作要么采用
ArraySegment
要么采用
byte[]
后跟偏移量和计数。如果您真的无法更改写入方法,那么不幸的是,您只能创建一个新数组并将数据复制到其中。

如果方法签名是
(byte[])
,则只能进行复制

如果您可以更改签名:

  • 流支持写入数组的子集,因此请求具有以下签名并不罕见:

    公共摘要无效写入(
    字节[]缓冲区,
    整数偏移,
    整数计数)

  • 另一个选项是传递
    IEnumerable
    ,这样就可以按任何方式切片数组,而无需复制


    • Buffer.BlockCopy将是我的选择

      Microsoft示例:

      您的代码如下所示:

      uncompressedData = GetNextUncompressedBlock();      
      int compressedLength = compress(buffer, uncompressedData);
      Buffer.BlockCopy(buffer, 0, buffer, 0, compressedLength);
      

      你不可能做到。与其更改数组的长度,不如将其复制到新的数组实例

      但是,您可以使用性能更好的:

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

      这符合您的需要,因为您有一个字节数组,字节是基本类型。

      byte[]b=newbyte[]{1,2,3,4,5};
      
          byte[] b = new Byte[] {1, 2, 3, 4, 5};
          IEnumerable<Byte> middle = b.Skip(2).Take(3);
      
      IEnumerable middle=b.Skip(2)、Take(3);

      这会让你得到任何你喜欢的中间部分。这很可能是一个副本,但我认为您不应该试图避免这种情况。

      哇,您以前曾帮助我使用WCF(作为一个不同的用户)。再次感谢Carlos+1的提示。
          byte[] b = new Byte[] {1, 2, 3, 4, 5};
          IEnumerable<Byte> middle = b.Skip(2).Take(3);