2009-02-18 33 views
27

Tengo un BitArray con la longitud de 8, y necesito una función para convertirlo a byte. ¿Cómo hacerlo?Convertir de BitArray a Byte

Específicamente, necesito una función correcta de ConvertToByte:

BitArray bit = new BitArray(new bool[] 
{ 
    false, false, false, false, 
    false, false, false, true 
}); 

//How to write ConvertToByte 
byte myByte = ConvertToByte(bit); 
var recoveredBit = new BitArray(new[] { myByte }); 
Assert.AreEqual(bit, recoveredBit); 

Respuesta

40

Esto debería funcionar:

byte ConvertToByte(BitArray bits) 
{ 
    if (bits.Count != 8) 
    { 
     throw new ArgumentException("bits"); 
    } 
    byte[] bytes = new byte[1]; 
    bits.CopyTo(bytes, 0); 
    return bytes[0]; 
} 
+6

Mente: esto calcula los bits en orden inverso, p. Ej. ¡BitArray del ejemplo se convertirá en 128, no en 1! – tehvan

+0

¿Por qué sucede esto en orden inverso? –

+1

@kornelijepetak: Así es como funciona BitArray, en términos de la forma en que elige copiar valores. –

4

Esto debería hacer el truco. Sin embargo, la respuesta anterior es probablemente la mejor opción.

public byte ConvertToByte(BitArray bits) 
    { 
     if (bits.Count > 8) 
      throw new ArgumentException("ConvertToByte can only work with a BitArray containing a maximum of 8 values"); 

     byte result = 0; 

     for (byte i = 0; i < bits.Count; i++) 
     { 
      if (bits[i]) 
       result |= (byte)(1 << i); 
     } 

     return result; 
    } 

En el ejemplo que ha publicado, el byte resultante será 0x80. En otras palabras, el primer valor en el BitArray corresponde al primer bit en el byte devuelto.

5

solución de un hombre pobre: ​​

protected byte ConvertToByte(BitArray bits) 
{ 
    if (bits.Count != 8) 
    { 
     throw new ArgumentException("illegal number of bits"); 
    } 

    byte b = 0; 
    if (bits.Get(7)) b++; 
    if (bits.Get(6)) b += 2; 
    if (bits.Get(5)) b += 4; 
    if (bits.Get(4)) b += 8; 
    if (bits.Get(3)) b += 16; 
    if (bits.Get(2)) b += 32; 
    if (bits.Get(1)) b += 64; 
    if (bits.Get(0)) b += 128; 
    return b; 
} 
27

Un post poco tarde, pero esto funciona para mí:

public static byte[] BitArrayToByteArray(BitArray bits) 
{ 
    byte[] ret = new byte[(bits.Length - 1)/8 + 1]; 
    bits.CopyTo(ret, 0); 
    return ret; 
} 

trabaja con:

string text = "Test"; 
byte[] bytes = System.Text.Encoding.ASCII.GetBytes(text); 
BitArray bits = new BitArray(bytes); 
bytes[] bytesBack = BitArrayToByteArray(bits); 
string textBack = System.Text.Encoding.ASCII.GetString(bytesBack); 
// bytes == bytesBack 
// text = textBack 

.

+11

En lugar de" bits.Length/8 ", debe usar" (bits.Length - 1)/8 + 1 "; de lo contrario, si el BitArray tiene una longitud de 7, su matriz de bytes lo hará estar vacío La parte "- 1" asegura que un múltiplo de 8 no regresará más uno. Gracias a http://stackoverflow.com/questions/17944/how-to-round-up-the-result-of-integer-division/503201#503201 – iano

+1

Buen punto. Un Math.Max ​​(1, bits.Length/8) también funcionará, supongo (un poco más legible). Siempre opero en bytes de 8 bits, así que no he considerado la condición de subdesbordamiento. –

+1

@TeddHansen ¿Qué tal 15? –

2

Ese debe ser el último. Funciona con cualquier longitud de matriz.

private List<byte> BoolList2ByteList(List<bool> values) 
    { 

     List<byte> ret = new List<byte>(); 
     int count = 0; 
     byte currentByte = 0; 

     foreach (bool b in values) 
     { 

      if (b) currentByte |= (byte)(1 << count); 
      count++; 
      if (count == 7) { ret.Add(currentByte); currentByte = 0; count = 0; };    

     } 

     if (count < 7) ret.Add(currentByte); 

     return ret; 

    } 
+0

Creo que aquí hay un error, ya que 'count ++;' ya se activó, la siguiente línea debería ser 'if (count == 8) {...}' –

0
byte GetByte(BitArray input) 
{ 
    int len = input.Length; 
    if (len > 8) 
    len = 8; 
    int output = 0; 
    for (int i = 0; i < len; i++) 
    if (input.Get(i)) 
     output += (1 << (len - 1 - i)); //this part depends on your system (Big/Little) 
     //output += (1 << i); //depends on system 
    return (byte)output; 
} 

Saludos!

0

pequeño convertidor de matriz de bytes endian: En primer bit (indexada con "0") en el BitArray supone que representa el bit menos significativo (bit más a la derecha en el bit-octeto) que interpreta como "cero" o "uno" como binario .

public static class BitArrayExtender { 

    public static byte[] ToByteArray(this BitArray bits) { 

     const int BYTE = 8; 
     int length = (bits.Count/BYTE) + ((bits.Count % BYTE == 0) ? 0 : 1); 
     var bytes = new byte[ length ]; 

     for (int i = 0; i < bits.Length; i++) { 

      int bitIndex = i % BYTE; 
      int byteIndex = i/BYTE; 

      int mask = (bits[ i ] ? 1 : 0) << bitIndex; 
      bytes[ byteIndex ] |= (byte)mask; 

     }//for 

     return bytes; 

    }//ToByteArray 

}//class 
1

Además de @JonSkeet contesta, puede utilizar el método genérico como golpe:

public static byte ToByte(this BitArray bits) 
     { 
      if (bits.Count != 8) 
      { 
       throw new ArgumentException("bits"); 
      } 
      byte[] bytes = new byte[1]; 
      bits.CopyTo(bytes, 0); 
      return bytes[0]; 
     } 

Y utilizar como:

BitArray foo = new BitArray(new bool[] 
{ 
    false, false, false, false,false, false, false, true 
}); 

foo.ToByte(); 
0

Por desgracia, la clase BitArray se implementa parcialmente en .Net Clase principal (UWP). Por ejemplo, la clase BitArray no puede llamar a los métodos CopyTo() y Count(). Escribí esta extensión para llenar la brecha:

public static IEnumerable<Byte> ToBytes(this BitArray bits, bool MSB = false) 
    { 
     int bitCount = 7; 
     int outByte = 0; 

     foreach (bool bitValue in bits) 
     { 
      if (bitValue) 
       outByte |= MSB ? 1 << bitCount : 1 << (7 - bitCount); 
      if (bitCount == 0) 
      { 
       yield return (byte) outByte; 
       bitCount = 8; 
       outByte = 0; 
      } 
      bitCount--; 
     } 
     // Last partially decoded byte 
     if (bitCount < 7) 
      yield return (byte) outByte; 
    } 
} 

El método decodifica la BitArray a una matriz de bytes usando la lógica LSB (menos significativo Byte). Esta es la misma lógica utilizada por la clase BitArray. Llamar al método con el parámetro MSB establecido en verdadero producirá una secuencia de bytes decodificados MSB. En este caso, recuerde que tal vez también necesite invertir la colección final de bytes de salida.