Pregunta

I tiene una matriz de 128 booleanos que representan bits. ¿Cómo puedo convertir estas representaciones 128 bits en 16 bytes?

Ejemplo:

Tengo una matriz que tiene el siguiente aspecto:

0110001100110000100010111011001011010011010001010001101101001100
1000010000000000001000111111111101000011111001111011111011111001

(convertido a 1s y 0s a ser más concisa)

Necesito convertir esos bits a la siguiente matriz de bytes:

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

EDIT: Esto no parece funcionar:

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

Se da salida:

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

Solución

El código está tratando el primer bit como el bajo bit de la palabra, por lo que terminan con cada palabra invertida. Como una solución rápida y sucia-, intente lo siguiente:

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

Eso pone el primer bit en la matriz en la posición más alta en el primer byte, etc.

Otros consejos

No sé si hay una forma automática de hacerlo, pero se puede hacer con un simple algoritmo.

algoritmo simple:

  1. Crea una matriz de bytes que se van a utilizar como su búfer de salida, e inicializar todos bytes en 0. El tamaño de esta matriz debe basarse en la longitud de su entrada de matriz booleana: ceil (bool_array_length / 8,0)

  2. Declarar una variable índice para ser utilizado como su byte actual y ponerlo a 0. Esto es el índice en el búfer de salida.

  3. iterar sobre cada elemento del array entrada booleana.
    3.1. Dejó poco cambiar el número 1 por el índice de matriz mod 8. Llame a este número de su máscara.
    3.2. Calcular su índice de byte como su índice actual en la matriz div 8.
    3.3. Si usted tiene un valor booleano true el índice actual de su matriz booleana de entrada, hacer una bitwise OR con su byte actual y su máscara.

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

EDIT: En realidad esto también devuelve:

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

endianness incorrecto? Voy a dejar de responder de todos modos, para referencia.


Edit: se pueden utilizar BitArray.CopyTo () mediante la inversión de las matrices de esta manera:

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

Prueba esta función (escrito como un método de extensión).

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: Es un error si el número de bits (Bools) no es un múltiplo de 8, pero a juzgar por su pregunta a este no es el caso. Sólo se requeriría una muy pequeña modificaiton para permitir matrices de bits de cualquier longitud.

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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top