Как я могу конвертировать биты в байты?

У меня есть массив из 128 логических значений, которые представляют биты. Как я могу преобразовать эти 128-битные представления в 16 байтов?

Пример:

У меня есть массив, который выглядит так:

0110001100110000100010111011001011010011010001010001101101001100
1000010000000000001000111111111101000011111001111011111011111001

(Преобразовано в 1 и 0, чтобы быть более кратким)

Мне нужно преобразовать эти биты в следующий байтовый массив:

99 48 139 178 211 69 27 76 132 0 35 255 67 231 190 249

РЕДАКТИРОВАТЬ: Это не похоже на работу:

public byte[] ToByteArray() {
    int numBytes = Count / 8;

    if (_bits.Count % 8 != 0) numBytes++;

    byte[] bytes = new byte[numBytes];

    int byteIndex = 0, bitIndex = 0;

    for (int i = 0; i < _bits.Count; i++) {
        if (_bits[i])
            bytes[byteIndex] |= (byte)(1 << bitIndex);

        bitIndex++;
        if (bitIndex == 8) {
            bitIndex = 0;
            byteIndex++;
        }
    }

    return bytes;
}

Это выводит:

198 12 209 77 203 162 216 50 33 0 196 255 194 231 125 159

5 ответов

Решение

Код рассматривает первый бит как младший бит слова, так что в итоге вы возвращаете каждое слово в обратном порядке. В качестве быстрого и грязного решения попробуйте это:

bytes[byteIndex] |= (byte)(1 << (7-bitIndex));

Это помещает первый бит в массиве в самую верхнюю позицию в первом байте и т. Д.

bool[] bools = ...
BitArray a = new BitArray(bools);
byte[] bytes = new byte[a.Length / 8];
a.CopyTo(bytes, 0);

РЕДАКТИРОВАТЬ: На самом деле это также возвращает:

198 12 209 77 203 162 216 50 33 0 196 255 194 231 125 159

Неправильный порядок байтов? Я все равно оставлю ответ, для справки.


РЕДАКТИРОВАТЬ: Вы можете использовать BitArray.CopyTo(), обращая массивы следующим образом:

bool[] bools = ...
Array.Reverse(bools); // NOTE: this modifies your original array
BitArray a = new BitArray(bools);
byte[] bytes = new byte[a.Length / 8];
a.CopyTo(bytes, 0);
Array.Reverse(bytes);

Я не знаю, есть ли автоматический способ сделать это, но вы можете сделать это с помощью простого алгоритма.

Простой алгоритм:

  1. Создайте массив байтов, который будет использоваться в качестве выходного буфера, и инициализируйте все байты равными 0. Размер этого массива должен основываться на длине вашего входного логического массива: ceil(bool_array_length / 8.0)

  2. Объявите индексную переменную, которая будет использоваться в качестве текущего байта, и установите для нее значение 0. Это содержит индекс в вашем выходном буфере.

  3. Итерируйте по каждому элементу во входном логическом массиве.
    3.1. Левый бит сдвигает номер 1 на индекс индекса массива 8. Назовите этот номер своей маской.
    3.2. Рассчитайте свой байтовый индекс как текущий индекс в массиве div 8.
    3.3. Если у вас есть логическое значение true значение текущего индекса во входном логическом массиве, выполните bitwise OR с вашим текущим байтом и вашей маской.

Попробуйте эту функцию (написано как метод расширения).

public byte[] ToByteArray(this bool[] bits)
{
    var bytes = new byte[bits.Length / 8];
    for (int i = 0, j = 0; j < bits.Length; i++, j += 8)
    {
        // Create byte from bits where LSB is read first.
        for (int offset = 0; offset < 8; offset++)
            bytes[i] |= (bits[j + offset] << offset);
    }

    return bytes;
}

Примечание: он потерпит неудачу, если число битов (bools) не кратно 8, но, судя по вашему вопросу, это не так. Для разрешения битовых массивов любой длины потребуется лишь очень небольшая модификация.

private static byte[] GetBytes(string bitString)
{
    byte[] result = Enumerable.Range(0, bitString.Length / 8).
        Select(pos => Convert.ToByte(
            bitString.Substring(pos * 8, 8),
            2)
        ).ToArray();

    List<byte> mahByteArray = new List<byte>();
    for (int i = result.Length - 1; i >= 0; i--)
    {
        mahByteArray.Add(result[i]);
    }

    return mahByteArray.ToArray();
}

private static String ToBitString(BitArray bits)
{
    var sb = new StringBuilder();

    for (int i = bits.Count - 1; i >= 0; i--)
    {
        char c = bits[i] ? '1' : '0';
        sb.Append(c);
    }

    return sb.ToString();
}
Другие вопросы по тегам