Как сформировать и распарсить битовый пакет в .Net?

Есть задача, в которой по сети требуется передавать пакеты.
Сами пакеты представляют из себя набор бит, не выравненных до байтов.

Например, вот такой пакет: 4 байта смещения, 1 бит - состояние, 23 бита - широта, 24 бита - долгота, 12 бит - высота, 7 байт пропускаем, 11 бит - скорость относительно оси север-юг, 11 бит - скорость относительно оси запад-восток.

Встаёт вопрос, как средствами современного .Net сформировать такой пакет и распарсить его?
Если бы данные были выравнены до кратных 8, то можно было бы использовать тот же BitArray, однако в этой ситуации он ругается при той же попытке вызвать CopyTo() в какой-нибудь byte[].
Также при "ровных" данных была бы возможность использовать SequenceReader да и в принципе System.Buffers, однако в SequenceReader не умеет читать заданное количество бит.

Использовать битовые маски не хотелось бы. Может, чего-то упускаю из имеющихся возможностей? Как реализовать работу с такими пакетами?
  • Вопрос задан
  • 161 просмотр
Решения вопроса 2
vabka
@vabka Куратор тега C#
Токсичный шарпист
Использовать битовые маски не хотелось бы.

А вот только их и остаётся использовать.
Ответ написан
Комментировать
twobomb
@twobomb
Можно примерно так
static void Main(string[] args)
        {

            CustomPackage cp = new CustomPackage();
            cp.offset = 3;
            cp.state = true;
            cp.latitude = new BitArray(23);
            cp.latitude.SetAll(true);
            cp.longitude= new BitArray(24);
            cp.longitude.SetAll(false);
            cp.height= new BitArray(24);
            cp.height.SetAll(true);
            cp.speedNS= new BitArray(11);
            cp.speedNS.SetAll(true);
            cp.speedWE = new BitArray(11);
            cp.speedWE.SetAll(true);

            var bytes = cp.toBytes();//Пакет в байты 

            var p = CustomPackage.FromBytes(bytes);//Пакет из байтов
        }

            
    }

    
    public class CustomPackage{
        public int offset;// 4 байта смещения
        public bool state;//1 бит - состояние
        public BitArray latitude = new BitArray(23);//23 бита - широта, 
        public BitArray longitude = new BitArray(24);//24 бита - долгота 
        public BitArray height = new BitArray(12);//12 бит - высота
        // 7 бит пропускаем, 
        public BitArray speedNS = new BitArray(11);// 11 бит - скорость относительно оси север-юг, 
        public BitArray speedWE = new BitArray(11);//11 бит - скорость относительно оси запад-восток.


        public static CustomPackage FromBytes(byte[] arr){
            CustomPackage cp = new CustomPackage();
            BitArray bt = new BitArray(arr);
            int ptr = 0;
            cp.offset = BitConverter.ToInt32(arr, ptr);
            ptr += 32;
            cp.state = bt[ptr++];
            cp.latitude = cp.utilCopyBits(bt, ptr, 23);
            ptr += 23;
            cp.longitude= cp.utilCopyBits(bt, ptr, 24);
            ptr += 24;
            cp.height= cp.utilCopyBits(bt, ptr, 12);
            ptr += 12;
            ptr += 7;
            cp.speedNS= cp.utilCopyBits(bt, ptr, 11);
            ptr += 11;
            cp.speedWE= cp.utilCopyBits(bt, ptr, 11);

            return cp;
        }

        public byte[] toBytes(){
            byte[] buff = new byte[16];
            int ptr = 0;
            utilWrite(ref ptr, ref buff, new BitArray(BitConverter.GetBytes(offset)),32);
            utilWrite(ref ptr, ref buff, new BitArray(BitConverter.GetBytes(state)), 1);
            utilWrite(ref ptr, ref buff, latitude,23);
            utilWrite(ref ptr, ref buff, longitude,24);
            utilWrite(ref ptr, ref buff, height,12);
            ptr += 7;// 7 бит пропускаем
            utilWrite(ref ptr, ref buff, speedNS, 11);
            utilWrite(ref ptr, ref buff, speedWE, 11);

            return buff;
        }

        private BitArray utilCopyBits(BitArray source, int offset, int length)
        {
            BitArray b = new BitArray(length);
            for (int i = 0; i < length; i++)
                b[i] = source[offset + i];
            return b;
        }
        private void utilWrite(ref int ptr, ref byte[] buff, BitArray writeData, int writeBitLength){
            BitArray bt = new BitArray(buff);
            for (int i = 0; i < writeBitLength; i++)
                bt.Set(ptr++, writeData[i]);
            bt.CopyTo(buff,0);
        }
    }
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Zoominger
@Zoominger
System Integrator
Мб глупость скажу, но почему бы не собрать эти биты в байты (с дописыванием в последний байт недостающих битов) и не перегнать эти байты в string вида "00110011" и не ковырять каждый бит, как char из string? А формировать такой пакет просто, если бит перегнать в hex и передавать именно hex'ы.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы