简体   繁体   English

从 C# 中的字节数组中读取字节的最有效方法是什么

[英]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}那么您的解析/查找将获得上述的开始和结束索引字节数组为211 ,长度为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.BlockCopyArray.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.

相关问题 使用SqlDataReader(C#)从SQL Server读取许多字节的最有效方法是什么 - What is the most efficient way to read many bytes from SQL Server using SqlDataReader (C#) 在C#中将字节数组保存为磁盘上文件的最有效方法是什么? - What is the most efficient way to save a byte array as a file on disk in C#? 从C#中的队列中取出字节的最有效方法 - Most efficient way to dequeue bytes from Queue in C# 从COM流读取到c#byte []的内存有效方法 - memory efficient way to read from COM stream to c# byte[] 在C#中从文本文件中读取大量整数(双精度)的最有效方法是什么? - What is the most efficient way to read a lot of integers (doubles) from text file in C#? 使用 C#,将包含二进制数据的字符串转换为字节数组的最有效方法是什么 - Using C#, what is the most efficient method of converting a string containing binary data to an array of bytes 获取通过编码创建的字节数的最有效方法是什么? - What is the most efficient way to get the amount of bytes created from encoding? 从字节数组C#中读取特定的字节 - Read Specific Bytes Out of Byte Array C# 在字节数组中查找模式的最有效方法 - Most efficient way to find pattern in byte array 在 C# 中将字节流写入文件的有效方法是什么? - What is the efficient way to write stream of bytes into a file in c#?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM