简体   繁体   English

如何从byte []数组中获取数组的一部分

[英]How can I get part of the array from a byte[] array

I have a byte[] array, mostly only part of array is used while the rest are 0x00. 我有一个byte []数组,大部分仅使用数组的一部分,其余部分为0x00。 In this case, how can I get only the array elements that are needed and not the entire array? 在这种情况下,如何仅获取所需的数组元素而不是整个数组? I have a int rxlen which would be the length of actual elements in the array. 我有一个int rxlen,它将是数组中实际元素的长度。

Example: 例:

byte[] framessent = {0xff, 0x53, 0x7e, 0x80, 0x00, 0x07, 0x60, 0x96, 0x2d, 0x00, 0x00.....} 
byte[] framereceived = {0xff, 0x53, 0x7e, 0x80, 0x00, 0x07, 0x60, 0x96, 0x2d, 0x00, 0x00.....}

framesent is usually 150 bytes, which I have a control on but framereceived is 300. I would like to simply compare the array elements (valid data) between framesent and framereceived and not the 0x00 that follows. frameent通常为150字节,我可以控制它,但是framereceived为300字节。我想简单比较一下frameent和framereceived之间的数组元素(有效数据),而不是后面的0x00。

I tried using Buffer.BlockCopy and Array.Copy as follows but I still get the entire array and not the ones I need. 我尝试如下使用Buffer.BlockCopy和Array.Copy,但是我仍然可以得到整个数组,而不是我需要的数组。

Buffer.BlockCopy(RxBuffer, 0, framereceived, 0, rxlen);

使用一些扩展方法,您可以从原始数组中获取rxlen ,如下所示:

var newArray = framereceived.Take(rxlen).ToArray();

I roughly have an idea of what you need (Apologies if I'm wrong). 我大致了解您的需求(如果我错了,我们深表歉意)。 If you need to take the elements of framereceived that are not 0x00 , use Linq: 如果需要采用 0x00framereceived元素,请使用Linq:

byte[] validbytes = framereceived.Where(frame => frame != 0x00).ToArray();

If you need to compare the data between the two arrays and get only the elements that are contained in both arrays, Linq can do that as well (My method might not be efficient): 如果需要比较两个数组之间的数据并仅获取两个数组中包含的元素,Linq也可以做到这一点(我的方法可能无效):

byte[] validbytes = framereceived.Where(frame => framessent.Contains(frame)).ToArray();

If you need to take bytes from a specific index of a specific length, use .Skip() and .Take() . 如果需要从特定长度的特定索引中获取字节,请使用.Skip().Skip() .Take()

If there is a possibility that your data arrives in several chunks, doing this check might be a little bit more complex, actually. 如果您的数据有可能分成几部分到达,那么执行此检查实际上可能会稍微复杂一点。

First of all, I would not use an array to store incoming data, but rather enqueue it in a FIFO (ie a Queue<byte> ). 首先,我不会使用数组来存储传入的数据,而是将其放入FIFO(即Queue<byte> )中。 Meaning that your receiving event handler would look something like: 这意味着您的接收事件处理程序将类似于:

// this is the byte "producer" part
private readonly Queue<byte> _inputQueue = new Queue<byte>();
void OnDataReceived(byte[] data)
{
    foreach (var b in data)
        _inputQueue.Enqueue(b);  

    ConsumeData();
}

And then you "consume" the incoming data, which in your case means you would be comparing it to an array of fixed size, something like: 然后“消耗”传入的数据,这意味着您将把它与固定大小的数组进行比较,例如:

void ConsumeData()
{
    if (_inputQueue.Count < framessent.Length)
         return;

    int index = 0;
    foreach (var item in _inputQueue)
    {
        // item doesn't match?
        if (item != framessent[index++])
        {
            // data doesn't match
            OnFailed();
            return;
        }

        // reached the end of the array?
        if (index >= _inputQueue.Length)
        {
            // data matches
            OnSuccess();
            return;
        }
}

The following question you need to ask is what happens if the data indeed doesn't match (eg one of the bytes doesn't match). 您需要问的以下问题是,如果数据确实不匹配(例如,字节之一不匹配),将会发生什么。 What do you do? 你是做什么? Skipping a single byte and retrying might be the most sensible thing to do, meaning the ConsumeData method might be rewritten to look something like: 跳过单个字节然后重试可能是最明智的做法,这意味着ConsumeData方法可能被重写为如下所示:

void ConsumeData()
{
    while (_inputQueue.Count < framessent.Length)
    {
        int index = 0;
        bool success = false;
        foreach (var item in _inputQueue)
        {
            // item doesn't match?
            if (item != framessent[index++])
            {
                // data doesn't match
                success = false;
                break;
            }

            // reached the end of the array?
            if (index >= _inputQueue.Length)
            {
                // data matches
                success = true;
                break;
            }
        }

        if (success)
        {
            OnSuccess();
            return;
        }
        else
        {
            // remove first byte and retry
            _inputQueue.Dequeue();
        }
    }
}

You will also need to take timeouts into account. 您还需要考虑超时问题。 If your ConsumeData method is not called in a while, it's a timeout and the operation should fail. 如果您的ConsumeData方法有一段时间没有被调用,则表示超时,操作将失败。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM