从 byte 数组中查找匹配内容的索引

本文介绍了一种从缓存byte数组中查找并定位多种报文帧头的方法,通过使用Java提供的数组比较方法,简化了查找过程,并提供了一段示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从 byte 数组中查找匹配内容的索引

在处理串口数据时,我们一般会这么处理:

先用一个缓存 byte 数组来缓存接收到的串口数据,然后在另一个处理线程中,再从缓存 byte 数组中查找特定标识(报文帧头)信息,然后截取出我们需要的数据,进行处理。

截取数据是需要开始索引的,这个问题就转换为要定位每一帧数据在缓存数组中的开始索引是多少。

当只有一种标识(报文帧头)时,还是比较容易处理的,从一大串的缓存 byte 数组中,挨个去比较,当完全和标识相等时,将此时的 index 返回,就是这一帧数据的开始位置了,然后配合报文长度,就可以把数据从缓存中截取出来。

大致代码如下:

public static int indexOf(byte[] first,byte[] meta)
    {
        int result = -1;
        boolean isExists = false;
        for (int i = 0; i < first.length - meta.length; i++)
        {
            isExists = true;
            for(int j = 0; j < meta.length; j++)
            {
                if(first[i+j] != meta[j])
                {
                    isExists = false;
                    break;
                }
            }
            if(isExists)
            {
                result = i;
                break;
            }
        }
        return result;
    }

假如我们收到的数据中,有多种标识(报文帧头)时,那我们有什么好的方法来查找到不同标识的索引呢。

可以仿照上文示例代码的思路,首先从数据中取出一个字节,和 A 标识的第一个字节比较,查看是否相等,如果相等,则继续从数据中取出第二个字节,和 A 标识的第二个字节是否相等,如果相等,继续重复操作,如果不相等,则需要从数据中取出第一个字节,和 B 标识的第一个字节比较,如此循环往复。

这样实现起来感觉好麻烦有木有?

好在 Java 系统提供了一个数组比较的方法,就避免了一个字节一个字节的比较了,直接一组字节比较,这样我们上述思路就简便了很多。

比如我们的标识(报文帧头)是一个 4 字节的数组,那么我们可以一次性取出 4 个字节和 A 标识比较,如果相等,则表明该信息是 A 标识的,如果不相等就和 B 标识进行比较,如果都不相等,缓存 byte 数组的索引 +1,再循环往复。

// 假设这里有两个帧头标识,长度都为 4
public void foo() {
	byte[][] metas = new byte[][]{{0x00, 0x00, 0x01, (byte) 0xd1},

                {0x14, (byte) 0xEF, (byte) 0x82, (byte) 0xEB}};

	// 这里是测试数据,我们需要定位到帧头开始索引,也就是 index = 2 和 index = 6
 	byte[] data= new byte[]{(byte) 0xAA, (byte) 0xAA, 0x00, 0x00, 0x01, (byte) 0xd1, 
0x14, (byte) 0xEF, (byte) 0x82, (byte) 0xEB};

	indexOf(data, metas, 4);
}
// 这里是示例方法,当找到匹配的帧头数组时,终止循环,返回 index
public static int indexOf(byte[] data, byte[][] meta, int metaDataLength)
    {
        int result = -1;
        boolean isExists = false;

        for (int i = 0; i <= data.length - metaDataLength; i++) {
            System.out.println("i-->" + i);
            byte[] temp = new byte[metaDataLength];
            System.arraycopy(data, i, temp, 0, temp.length);
            for (int j = 0; j < meta.length; j++) {
                if(Arrays.equals(temp, meta[j])) {
                    System.out.println("equal-->" + i);
                    isExists = true;
                    break;
                }
            }
            if (isExists) {
                result = i;
                break;
            }
        }
        return result;
    }

示例方法中,我只返回了缓存 byte 数组中的索引,我们应该还要返回这个索引是哪个帧头信息的才可以,所以返回值需要是一个 Java bean 类,包含两个信息,一个是 byte 数组中的索引信息,一个是帧头信息。

END

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值