【问题标题】:C# How to find a byte array inside a byte array going reverse?C#如何在反向的字节数组中找到一个字节数组?
【发布时间】:2016-01-22 06:38:48
【问题描述】:

我正在尝试在另一个字节数组 byte[] 中找到一个字节数组 byte[] 反向。

问题:如何在另一个字节数组中从头到尾搜索一个字节数组?

此链接是我正在制作的代码的参考 c# How to Continuously find a byte array inside a byte array?

编辑:我需要将此代码转换为在另一个反向字节数组中搜索字节数组。

        indexPos = SearchBytes(input, find, indexPos);

        Console.WriteLine("Found at " + indexPos);

        indexPos += find.Length;

更新:当我点击按钮时,索引需要搜索如下:11, 6 1

我需要从头到尾搜索以下代码:

byte[] input = { 0, 1, 1, 1, 5, 6, 1, 1, 1, 7, 8, 1, 1, 1 };
    byte[] find = { 1, 1, 1 };
    int indexPos = 0;

    private void button1_Click(object sender, EventArgs e)
    {
        indexPos = SearchBytes(input, find, indexPos);

        Console.WriteLine("Found at " + indexPos);

        indexPos += find.Length;
    }

    public int SearchBytes(byte[] haystack, byte[] needle, int start_index)
    {
        int len = needle.Length;
        int limit = haystack.Length - len;
        for (int i = start_index; i <= limit; i++)
        {
            int k = 0;
            for (; k < len; k++)
            {
                if (needle[k] != haystack[i + k]) break;
            }
            if (k == len) return i;
        }
        return -1;
    }

【问题讨论】:

  • 澄清一下:例如,如果您有haystack 0, 1, 1, 1, 1, 5, 6, 7, 8 并且您的needle1,您会返回14 作为索引位置吗?如果您的needle1 5,您会返回索引45,还是返回-1(未找到)?最后,如果您的needle5 1,您会返回45,还是返回-1(未找到)?
  • @Ian 我需要它返回到 4 然后 3 依此类推。
  • 我明白了,如果你有 haystack 1 2 1 2 1 2 会发生什么?如果你的针是1 2,你会返回 4 然后 2 然后 0 (注意我加粗了)?或者,您会从后面阅读2 1 2 1 2 1,因此最后一个将缺少2,您只会返回 4 然后 2?
  • @Ian haystack 0 1 0 0 1 1 0 needle 1 我需要它来按以下顺序查找数字:5、4、1。然后下一个索引将是 -1 以重新启动。我只是想让代码反转它的搜索。我将不胜感激。谢谢。
  • 我已经明白了,我正准备提供帮助,但我只是想知道你为什么在你的 needle 中使用 byte[] 而不是 byte,如果你只能有 1 个 byte。这就是为什么我不断给出多个字节的例子为needle。那么,你的needle 会不会只有 1 个byte?可以是多个字节吗?

标签: c# arrays search byte reverse


【解决方案1】:

您可以使用LINQ 查询以及Array.Reverse 来帮助您。


编辑:

要找到多字节的模式,你需要像这样更新LINQ查询

byte[] input = { 0, 1, 1, 1, 5, 6, 1, 1, 1, 7, 8, 1, 1, 1 };
byte[] find = { 1, 1, 1 };
int indexNow = 0;
int findLength = find.Length;
int[] indexes = (from i in input                                             
                let index = indexNow++
                where index <= input.Length - findLength //cannot exceeds this on the search
                let compared = input.Skip(index).Take(findLength)
                where Enumerable.SequenceEqual(find, compared)
                select index).Reverse().ToArray();

您的indexes 中的结果将是您想要的11,6,1

要使用函数,只需将上面使用的所有查询和输入放到返回 indexes 的函数中。

public int[] SearchBytes(byte[] input, byte[] find){
    int indexNow = 0;
    return (from i in input                                          
            let index = indexNow++
            where index <= input.Length - find.Length//cannot exceeds this on the search
            let compared = input.Skip(index).Take(find.Length)
            where Enumerable.SequenceEqual(find, compared)
            select index).Reverse().ToArray();    
}

原文:

假设您只定义了一个 byte needle,如 cmets 中所述,您可以这样做:

byte[] input = { 0, 1, 1, 1, 1, 5, 6, 7, 8 };
byte[] find = { 1 };
int indexNow = 0;
int[] indexes = (from i in input
                  let index = indexNow++
                  where i == find[0]                                        
                  select index).ToArray();
Array.Reverse(indexes);

您的indexes 中的结果将是您想要的4,3,2,1

现在如果你想用多个值搜索find

byte[] find = { 1, 0, 5, 6 };

然后你可以循环查询:

byte[] input = { 0, 1, 1, 1, 1, 5, 6, 7, 8 };
byte[] find = { 1, 0, 5, 6 };

List<int[]> indexesList = new List<int[]>();

foreach (byte findNow in find){
    int indexNow = 0;
    int[] indexes = (from i in input
                      let index = indexNow++
                      where i == find[0]                                        
                      select index).ToArray();
    Array.Reverse(indexes);
    indexesList.Add(indexes);
}

那么你所有的结果都将在indexesList 中,如下所示:

4, 3, 2, 1
0
5
6

【讨论】:

  • 您编写的代码正在运行,但我需要它来加快搜索速度。这个问题的原始代码对于我正在做的事情来说已经足够快了,但是你能把它转换成反向搜索并像我在这个问题中发布的原始代码一样快吗?
  • @JohnSmith 我认为这已经属于另一个问题了......:/可能有些人可以帮助您在代码审查中制定更快的算法。但是可能有些人也可以在 SO 中做到这一点。尝试使用更新后的代码将其作为新的(单独的)问题发布。
【解决方案2】:

这对我有用:

byte[] input = { 0, 1, 1, 1, 5, 6, 1, 1, 1, 7, 8, 1, 1, 1 };
byte[] find = { 1, 1, 1 };

var query =
    input
        .Select((x, n) => new
        {
            n,
            found = input.Skip(n).Take(find.Length).SequenceEqual(find)
        })
        .Where(x => x.found)
        .Select(x => x.n)
        .Reverse();

我收到{ 11, 6, 1 }

如果我开始:

byte[] input = { 0, 1, 0, 0, 1, 1, 0, };
byte[] find = { 1, };

...然后我得到{ 5, 4, 1 }


这是一个函数:

public IEnumerable<int> SearchBytes(byte[] haystack, byte[] needle)
{
    return
        haystack
            .Select((x, n) => new
            {
                n,
                found = haystack.Skip(n).Take(needle.Length).SequenceEqual(needle)
            })
            .Where(x => x.found)
            .Select(x => x.n)
            .Reverse();
}

【讨论】:

  • 我将如何使用您的答案来调用它?
  • 有点对,我仍然需要知道如何使用它。示例:indexPos = SearchBytes(input, find); indexPos += find.Length;
  • 它会生成一个IEnumerable&lt;int&gt;,您可以在foreach 中使用它,或者使用.ToList() 将其转换为列表。你需要如何使用它?
  • 我需要它给我一个int 值,这样我就可以获得字节数组的搜索索引。你能实现这个功能吗?
  • 在您的问题中,您要求它返回11, 6, 1。您希望它返回 .First() 值、.Last() 值还是 .ElementAt(n) 值?
猜你喜欢
  • 2012-07-07
  • 2016-04-27
  • 2014-02-15
  • 1970-01-01
  • 2019-11-17
  • 2015-06-09
  • 2023-03-15
  • 1970-01-01
相关资源
最近更新 更多