Чтение/запись сжатых двоичных данных
-
13-09-2019 - |
Вопрос
Я повсюду читал, что люди говорят о побитовом сжатии объектов.Такие вещи, как «Первые три бита представляют то-то и то-то, затем следующие два представляют это и двенадцать битов — то»
Я понимаю, почему хотелось бы минимизировать использование памяти, но не могу придумать, как это реализовать.Я знаю, что упаковал бы его в одно или несколько целых чисел (или длинных чисел, что угодно), но не могу представить себе простой способ с ним работать.Было бы очень здорово, если бы существовал класс, в котором я мог бы получать/устанавливать произвольные биты из двоичного поля произвольной длины, и он позаботился бы обо всем за меня, и мне не пришлось бы возиться с & и |' s и маски и все такое.
Есть ли стандартная схема для подобных вещей?
Решение
От MSDN:
Класс BitArray
Управляет компактным массивом битовых значений, которые представлены в виде логических значений, где true указывает, что бит включен (1), а false указывает, что бит выключен (0).
Пример:
BitArray myBitArray = new BitArray(5);
myBitArray[3] = true; // set bit at offset 3 to 1
Однако BitArray позволяет устанавливать только отдельные биты.Если вы хотите закодировать значения с большим количеством битов, вероятно, вам не придется возиться с & и |, масками и прочим :-)
Другие советы
Возможно, вы захотите проверить Битвектор32 структура в .NET Framework.Он позволяет вам определять «разделы», которые представляют собой диапазоны битов внутри целого числа, а затем читать и записывать значения в эти разделы.
Основное ограничение заключается в том, что оно ограничено одним 32-битным целым числом;это может быть проблемой, а может и не быть, в зависимости от того, что вы пытаетесь сделать.Как упоминалось в dtb, BitArray может обрабатывать битовые поля любого размера, но вы можете получать и устанавливать только один бит за раз — секции, как в BitVector32, не поддерживаются.
То, что вы ищете, называется побитовыми операциями.
Например, предположим, что мы собираемся представить значение RGB в младших 24 битах целого числа, где R — это биты 23–16, G — биты 15–8, а B — биты 7–0.
Вы можете установить R в любое значение от 0 до 255, не затрагивая другие биты, например:
void setR(ref int RGBValue, int newR)
{
int newRValue = newR << 16; // shift it left 16 bits so that the 8 low-bits are now in position 23-16
RGBValue = RGBValue & 0x00FF; // AND it with 0x00FF so that the top 16 bits are set to zero
RGBValue = RGBValue | newRValue; // now OR it with the newR value so that the new value is set.
}
Используя побитовые операции «И» и «ИЛИ» (а иногда и более экзотические операции), вы можете легко установить и очистить любой отдельный бит большего значения.
Я думаю, что вместо использования набора инструментов или классов-оболочек для конкретной платформы вам лучше стиснуть зубы и изучить свои &s, |s и 0x04, а также то, как работают все побитовые операторы.По большому счету, именно так и делается для большинства проектов, и операции выполняются очень быстро.Операции практически идентичны на большинстве языков, поэтому вы не будете зависеть от какого-то конкретного инструментария.