[英]what is the most efficient way to read bytes from a byte array in C#
I am trying to do this operation:我正在尝试执行此操作:
Sending a byte[] inputBuffer into a function将 byte[] inputBuffer 发送到 function
In that function I need to parse the array for eg在那个 function 我需要解析数组,例如
inputBuffer = {1A,2B,3C,4D,5F,6E,2A,3B,4C,6D} inputBuffer = {1A,2B,3C,4D,5F,6E,2A,3B,4C,6D}
I want to read 1A,2B and 3C first我想先读1A、2B和3C
Then 4D,5F,6E,2A,3B,4C,6D second然后 4D,5F,6E,2A,3B,4C,6D 第二
I need to use these two subarrays to do some operations (Hash and Encrypt them)我需要使用这两个子数组来做一些操作(哈希和加密它们)
Then I need to put them back into a new array with some extra bytes attach to it (length bytes)然后我需要将它们放回一个新数组中,并附加一些额外的字节(长度字节)
I don't want to use blockcopy since I don't think it's really efficient我不想使用块复制,因为我认为它不是很有效
Let's break down your steps, and try to make each step as efficient as possible (by efficient, we want to not copy data if we don't have to, and when we do, we copy it using the most efficient method).让我们分解您的步骤,并尝试使每个步骤尽可能高效(通过高效,我们不想复制数据,如果我们不需要,当我们这样做时,我们使用最有效的方法复制它)。
Sending a byte[] inputBuffer into a function
将 byte[] inputBuffer 发送到 function
That part is simply passing in the array, which does not do a copy of the array, just a copy of the array reference (and that won't even happen if .NET has inlined the method call).该部分只是传入数组,它不做数组的副本,只是数组引用的副本(如果 .NET 已内联方法调用,这甚至不会发生)。
void DoStuff(byte[] inputBuffer)
{
...
In that function I need to parse the array for eg
在那个 function 我需要解析数组,例如
inputBuffer = {1A,2B,3C,4D,5F,6E,2A,3B,4C,6D}
inputBuffer = {1A,2B,3C,4D,5F,6E,2A,3B,4C,6D}
Let's say your inputBuffer looks like {00, 00, 1A,2B,3C,4D,5F,6E,2A,3B,4C,6D, 00, 00}
then your parse/find would get the start and end index of the above array of bytes as 2 and 11 , for a length of 10 .假设您的 inputBuffer 看起来像
{00, 00, 1A,2B,3C,4D,5F,6E,2A,3B,4C,6D, 00, 00}
那么您的解析/查找将获得上述的开始和结束索引字节数组为2和11 ,长度为10 。
I want to read 1A,2B and 3C first
我想先读1A、2B和3C
Then 4D,5F,6E,2A,3B,4C,6D second
然后 4D,5F,6E,2A,3B,4C,6D 第二
You can slice the array twice, creating two ReadOnlySpan<byte>
, which use the underlying memory directly (no copying).您可以对数组进行两次切片,创建两个
ReadOnlySpan<byte>
,它们直接使用底层 memory (不复制)。 (see this reference for more info). (有关更多信息,请参阅此参考资料)。
var firstSlice = new ReadOnlySpan<byte>(inputBuffer, 2, 3); // index 2, for 3 bytes
var secondSlice = new ReadOnlySpan<byte> inputBuffer, 5, 7); // index 5 for 7 bytes
I need to use these two subarrays to do some operations (Hash and Encrypt them)
我需要使用这两个子数组来做一些操作(哈希和加密它们)
Do your hashing and encryption on these spans;在这些跨度上进行散列和加密; this doesn't change the spans, so you're still using the in-place memory.
这不会改变跨度,因此您仍在使用就地 memory。 If your hash/encryption routines can accept arrays with offsets, then you won't even need to give them the span treatment.
如果您的哈希/加密例程可以接受带有偏移量的 arrays,那么您甚至不需要对它们进行跨度处理。
Then I need to put them back into a new array with some extra bytes attach to it (length bytes)
然后我需要将它们放回一个新数组中,并附加一些额外的字节(长度字节)
I don't want to use blockcopy since I don't think it's really efficient
我不想使用块复制,因为我认为它不是很有效
You simply need to create the array,您只需要创建数组,
var result = new byte[10 + size-of-extra-data];
and copy the two slices and the extra data into that array using either Buffer.BlockCopy
, Array.Copy
a loop over bytes, or an unrolled loop.并使用
Buffer.BlockCopy
、 Array.Copy
字节循环或展开循环将两个切片和额外数据复制到该数组中。 (Note: if it's thread-safe, and you're working with same-size data each time, you can avoid the above allocation by reusing a preallocated result array). (注意:如果它是线程安全的,并且您每次都使用相同大小的数据,则可以通过重用预分配的结果数组来避免上述分配)。
Anyway, for your specific case (and by the way, benchmark it if it's in critical code), it seems like a loop or unrolled loop (which .NET will probably unroll anyway when optimizing the code) is your best bet.无论如何,对于您的特定情况(顺便说一下,如果它在关键代码中,对其进行基准测试),它似乎是一个循环或展开循环(在优化代码时 .NET 可能无论如何都会展开)是您最好的选择。
// this could be a loop, but I'm unrolling it here...
result[0] = firstSlice[0];
result[1] = firstSlice[1];
result[2] = firstSlice[2];
result[3] = secondSlice[0];
result[4] = secondSlice[1];
result[5] = secondSlice[2];
result[6] = secondSlice[3];
result[7] = secondSlice[4];
result[8] = secondSlice[5];
result[9] = secondSlice[6];
... // copy extra data from wherever it comes from
With your next best option being Array.Copy下一个最佳选择是Array.Copy
// just one copy since we are using the original source; it would be two if we used the spans
Array.Copy(inputBuffer, 2, result, 0, 10);
// now copy in the extra data
Array.Copy(extraData, 0, result, 10, extraData.Length);
or, with a similar signature, the Buffer.BlockCopy :或者,具有类似签名的Buffer.BlockCopy :
// just one copy since we are using the original source; it would be two if we used the spans
Buffer.BlockCopy(inputBuffer, 2, result, 0, 10);
// now copy in the extra data
Buffer.BlockCopy(extraData, 0, result, 10, extraData.Length);
The reference for the above assertions of efficiency comes from this highly upvoted SO answer .上述效率断言的参考来自这个高度赞成的SO answer 。
You don't need BlockCopy here, just do it in one loop.您在这里不需要 BlockCopy,只需在一个循环中完成即可。
List<int> inputValues = new List<int>{1, 2, 3, 4, 5};
List<int> indicesToPick = new List<int>{3, 4};
var result = new int[indicesToPick.Count];
int idx = 0;
foreach(var e in indicesToPick)
{
result[idx++] = inputValues[e];
}
Since you're picking individual elements only, you can't use BlockCopy (that can be used for copying a large section of an array).由于您只选择单个元素,因此不能使用 BlockCopy (可用于复制数组的大部分)。 The one allocation is required, as it will contain your result (unless it would be ok to overwrite the input).
需要一个分配,因为它将包含您的结果(除非可以覆盖输入)。
You may use Array.Copy()
instead of Buffer.BlockCopy()
and hope that following approach would work for you:您可以使用
Array.Copy()
而不是Buffer.BlockCopy()
并希望以下方法对您有用:
byte[5] oldArray = {1,2,3,4,5};
byte[3] newArray = new byte[3];
Array.Copy(oldArray, 1, newArray, 0, 3);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.