Pergunta

I têm uma matriz de 128 booleanos que representam bits. Como posso converter essas representações de 128 bits em 16 bytes?

Exemplo:

Eu tenho uma matriz que se parece com isso:

0110001100110000100010111011001011010011010001010001101101001100
1000010000000000001000111111111101000011111001111011111011111001

(convertido para 1s e 0s para ser mais conciso)

Eu preciso converter esses bits para a matriz byte seguinte:

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

EDIT: Este não parece trabalho:

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;
}

Ele produz:

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

Solução

O código está tratando o primeiro bit como o baixo bit da palavra, assim você acaba com cada palavra invertida. Como uma solução rápida e suja, tente o seguinte:

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

que coloca o primeiro bit na matriz na posição mais alta no primeiro byte, etc.

Outras dicas

Eu não sei se há uma maneira automática de fazer isso, mas você pode fazê-lo com um algoritmo simples.

algoritmo simples:

  1. Criar uma matriz de bytes que serão usados ??como o seu tampão de saída, e inicializar todos os bytes para 0. O tamanho desta matriz deve basear-se no comprimento da sua matriz de entrada booleana: ceil (bool_array_length / 8,0)

  2. Declare uma variável de índice a ser utilizado como o seu byte atual, e configurá-lo para 0. Isto é o índice em seu buffer de saída.

  3. iterar sobre cada elemento na sua matriz de boolean entrada.
    3.1. Esquerda mordeu mudar o número 1 pelo índice da matriz mod 8. Ligue para este número a sua máscara.
    3.2. Calcule seu índice de byte como seu índice atual na matriz div 8.
    3.3. Se você tem um valor true boolean o índice atual em sua matriz booleana de entrada, fazer um bitwise OR com o byte atual e sua máscara.

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

EDIT: Na verdade, este também retorna:

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

endianness errada? Vou deixar resposta de qualquer maneira, para referência.


EDIT: Você pode usar BitArray.CopyTo (), invertendo as matrizes assim:

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);

Tente esta função (escrito como um método de extensão).

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;
}

Nota: falhará se o número de bits (bools) não é um múltiplo de 8, mas a julgar pela sua pergunta não é esse o caso. Levaria apenas uma pequena modificaiton para matrizes de qualquer comprimento autorização bits.

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();
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top