Home > Enterprise >  LINQ ile Array Splitting
LINQ ile Array Splitting

Time:09-17

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();
  • Related