2009-02-18 19 views
27

Ho un BitArray con la lunghezza di 8 e ho bisogno di una funzione per convertirlo in un byte. Come farlo?Conversione da BitArray a Byte

In particolare, ho bisogno di un corretto funzionamento del 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); 

risposta

40

Questo dovrebbe funzionare:

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

Mind: questo calcola i bit in ordine inverso, ad es. il BitArray dell'esempio verrà convertito in 128, non 1! – tehvan

+0

Perché ciò avviene in ordine inverso? –

+1

@kornelijepetak: Questo è il modo in cui BitArray funziona, in base al modo in cui sceglie di copiare i valori. –

4

Questo dovrebbe fare il trucco. Tuttavia, la risposta precedente è probabilmente l'opzione migliore.

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

Nell'esempio che hai postato il byte risultante sarà 0x80. In altre parole, il primo valore nel BitArray corrisponde al primo bit nel byte restituito.

5

soluzione di un uomo povero:

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 po 'in ritardo post, ma questo funziona per me:

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

Compatibile 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

Invece di" bits.Length/8 ", dovresti usare" (bits.Length - 1)/8 + 1 ", altrimenti se il BitArray ha una lunghezza di 7, il tuo array di byte essere vuoto La parte "- 1" assicura che un multiplo di 8 non restituisca più uno. Grazie a http://stackoverflow.com/questions/17944/how-to-round-up-the-result-of-integer-division/503201#503201 – iano

+1

Buon punto. Un Math.Max ​​(1, bits.Length/8) funzionerà anche io credo (leggermente più leggibile). Io lavoro sempre su 8 bit byte quindi non ho considerato la condizione di underflow. –

+1

@TeddHansen Che dire di 15? –

2

Questo dovrebbe essere il massimo. Funziona con qualsiasi lunghezza di array.

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

Credo che ci sia un bug qui - dato che 'count ++;' ha già sparato, la riga successiva dovrebbe essere '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; 
} 

Cheers!

0

Piccolo convertitore matrice endian byte: primo bit (indicizzato con "0") nel BitArray presume rappresenta bit meno significativo (bit più a destra nel bit-ottetto) che interpretato come "zero" o "uno" come 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

Oltre a @JonSkeet Risposta Puoi usare il metodo generico come colpo:

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

E utilizzare come:

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

foo.ToByte(); 
0

Purtroppo, la classe BitArray è parzialmente implementata in .Net Core class (UWP). Ad esempio, la classe BitArray non è in grado di chiamare i metodi CopyTo() e Count(). Ho scritto questa estensione per colmare il vuoto:

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

Il metodo decodifica il BitArray una matrice di byte utilizzando la logica LSB (Less Significant Byte). Questa è la stessa logica utilizzata dalla classe BitArray. La chiamata del metodo con il parametro MSB impostato su true produrrà una sequenza byte decodificata MSB. In questo caso, ricorda che forse hai anche bisogno di invertire la raccolta finale dei byte in uscita.