为了账号安全,请及时绑定邮箱和手机立即绑定

字节[]数组模式搜索

/ 猿问

字节[]数组模式搜索

C#
慕盖茨4494581 2019-10-12 19:06:14

字节[]数组模式搜索

任何人都知道如何搜索/匹配字节[]数组中的字节模式,然后返回位置。

例如

byte[] pattern = new byte[] {12,3,5,76,8,0,6,125};byte[] toBeSearched = new byte[] {23,36,43,76,125,56,34,234,12,3,5,76,8,0,6,125,234,56,211,122,22,4,7,89,76,64,12,3,5,76,8,0,6,125}


查看完整描述

3 回答

?
杨魅力

我可以建议一些不涉及创建字符串、复制数组或不安全代码的内容:


using System;

using System.Collections.Generic;


static class ByteArrayRocks {


    static readonly int [] Empty = new int [0];


    public static int [] Locate (this byte [] self, byte [] candidate)

    {

        if (IsEmptyLocate (self, candidate))

            return Empty;


        var list = new List<int> ();


        for (int i = 0; i < self.Length; i++) {

            if (!IsMatch (self, i, candidate))

                continue;


            list.Add (i);

        }


        return list.Count == 0 ? Empty : list.ToArray ();

    }


    static bool IsMatch (byte [] array, int position, byte [] candidate)

    {

        if (candidate.Length > (array.Length - position))

            return false;


        for (int i = 0; i < candidate.Length; i++)

            if (array [position + i] != candidate [i])

                return false;


        return true;

    }


    static bool IsEmptyLocate (byte [] array, byte [] candidate)

    {

        return array == null

            || candidate == null

            || array.Length == 0

            || candidate.Length == 0

            || candidate.Length > array.Length;

    }


    static void Main ()

    {

        var data = new byte [] { 23, 36, 43, 76, 125, 56, 34, 234, 12, 3, 5, 76, 8, 0, 6, 125, 234, 56, 211, 122, 22, 4, 7, 89, 76, 64, 12, 3, 5, 76, 8, 0, 6, 125 };

        var pattern = new byte [] { 12, 3, 5, 76, 8, 0, 6, 125 };


        foreach (var position in data.Locate (pattern))

            Console.WriteLine (position);

    }

}

编辑(通过抽象) - 移动内容在这里,因为这不是一个答案


出于好奇,我创建了一个包含不同答案的小基准。


下面是一百万次迭代的结果:


solution [Locate]:            00:00:00.7714027

solution [FindAll]:           00:00:03.5404399

solution [SearchBytePattern]: 00:00:01.1105190

solution [MatchBytePattern]:  00:00:03.0658212



查看完整回答
反对 回复 2019-10-13
?
慕的地6264312

使用Linq方法

public static IEnumerable<int> PatternAt(byte[] source, byte[] pattern){
    for (int i = 0; i < source.Length; i++)
    {
        if (source.Skip(i).Take(pattern.Length).SequenceEqual(pattern))
        {
            yield return i;
        }
    }}

很简单!



查看完整回答
反对 回复 2019-10-13
?
茅侃侃

最初,我发布了一些我使用的旧代码,但对JBEvain的代码很好奇基准..我发现我的解决方案太慢了。看来布鲁诺·康德SearchBytePattern是最快的。我不明白为什么,特别是因为他使用了Array.Copy和扩展方法。但在JB的测试中有证据,所以对布鲁诺的评价。

我进一步简化了这些部分,希望这将是最清晰和最简单的解决方案。(Bruno Conde所做的所有艰苦工作)改进如下:

  • BlockCopy
  • Array.IndexOf<字节>
  • 循环而不是for循环。
  • 启动索引参数
  • 转换为可拓方法

    public static List<int> IndexOfSequence(this byte[] buffer, byte[] pattern, int startIndex)    {
       List<int> positions = new List<int>();
       int i = Array.IndexOf<byte>(buffer, pattern[0], startIndex);  
       while (i >= 0 && i <= buffer.Length - pattern.Length)  
       {
          byte[] segment = new byte[pattern.Length];
          Buffer.BlockCopy(buffer, i, segment, 0, pattern.Length);    
          if (segment.SequenceEqual<byte>(pattern))
               positions.Add(i);
          i = Array.IndexOf<byte>(buffer, pattern[0], i + 1);
       }
       return positions;    }

注意,while块应该是i = Array.IndexOf<byte>(buffer, pattern[0], i + 1);而不是i = Array.IndexOf<byte>(buffer, pattern[0], i + pattern.Length);..看看约翰的评论。一个简单的测试可以证明:

byte[] pattern = new byte[] {1, 2};byte[] toBeSearched = new byte[] { 1, 1, 2, 1, 12 };

带着i = Array.IndexOf<byte>(buffer, pattern[0], i + pattern.Length);什么也没回。i = Array.IndexOf<byte>(buffer, pattern[0], i + 1);返回正确的结果。



查看完整回答
反对 回复 2019-10-13

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信