I have a high size byte array. There are multiple packages in the array. It is unclear how many packages there are.
Package Structure => Header (0xAA 0xFE) Lenght (2 Byte) Data (Lenght Byte) Checksum (2 Byte)
I want to split the packages inside the big array into separate arrays. The algorithm below does this. Is it possible to do this with LINQ?
What I want to learn is how we can control complex structures with LINQ.
Can you help if it can be done with LINQ? Thank you from now.
List<byte[]> allPacket = new List<byte[]>();
public void LogReadBuffer(byte[] buffer)
{
try
{
for(long i = 0; i < buffer.Length;)
{
if(buffer[i] == (char)0xAA && buffer[i 1] == 0xFE && Step == 0)
{
Lenght = (short)(
((byte)buffer[i 2] << 8)
((byte)buffer[i 3] << 0));
packet = new byte[Lenght 6];
Step = 1;
}
else if(Step == 1)
{
for (int packetCounter = 0; packetCounter < Lenght 6; packetCounter )
{
packet[packetCounter] = buffer[i ];
}
allPacket.Add(packet);
Step = 0;
}
}
}
catch { }
}
CodePudding user response:
While I agree that built-in LINQ does not lend itself to irregular grouping, if you are willing to validate packages afterwards, or potentially have poorer error handling, an extension method makes for a simple LINQ statement.
This extension method groups data by using a method to determine the size of the next "chunk" of data, based on the data.
public static class LINQExt {
// int ChunkSizeFn(T[] data, int start) - returns size of chunk at start
public static IEnumerable<T[]> GroupByFunc<T>(this T[] data, Func<T[], int, int> ChunkSizeFn) {
int offset = 0;
while (offset < data.Length) {
var currentChunkLen = ChunkSizeFn(data, offset);
yield return new ArraySegment<T>(data, offset, currentChunkLen).ToArray();
offset = currentChunkLen;
}
}
}
Using this extension method, you can pull out the chunks:
var allPackages = buffer.GroupByFunc((data,start) => (data[start 2] << 8) data[start 3] 6).ToList();
To filter to only packages with valid Headers, add a Where
:
var allPackages = buffer
.GroupByFunc((data,start) => (data[start 2] << 8) data[start 3] 6)
.Where(p => p[0] == '\xAA' && p[1] == '\xFE')
.ToList();