Reputation: 157
I'm trying to find a byte array byte[]
inside another byte array byte[]
going reverse.
Question: How can I search a byte array inside another byte array from end to start?
This link is a reference of the code I'm making c# How to Continuously find a byte array inside a byte array?
EDIT: I need this code converted to searching for a byte arry within another byte array going reverse.
indexPos = SearchBytes(input, find, indexPos);
Console.WriteLine("Found at " + indexPos);
indexPos += find.Length;
UPDATED: When I click the button, the index needs to search as follows: 11, 6 1
This code below is what I need to have searching from end to start:
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;
}
Upvotes: 2
Views: 873
Reputation: 117029
This works for me:
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();
I get { 11, 6, 1 }
.
If I start with:
byte[] input = { 0, 1, 0, 0, 1, 1, 0, };
byte[] find = { 1, };
...then I get { 5, 4, 1 }
.
Here it is as a function:
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();
}
Upvotes: 1
Reputation: 30813
You can use LINQ
query as well as Array.Reverse
to help you.
Edit:
To find the pattern of multiple bytes, you need to update the LINQ
query like this
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();
And the result in your indexes
will be 11,6,1
as you wanted.
To use a function, simply put all the queries and inputs used above to a function returning 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();
}
Original:
Assuming you only define one byte
needle
as discussed in the comments, you could do it like this:
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);
And the result in your indexes
will be 4,3,2,1
as you wanted.
Now if you want to search for find
with multiple values:
byte[] find = { 1, 0, 5, 6 };
Then you could loop over the query:
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);
}
Then all your results will be in the indexesList
as follow:
4, 3, 2, 1
0
5
6
Upvotes: 2