1

I am getting a string that has been Base64 encoded from a byte[] data, and I have to check the bits inside it.

When I get "AAAB", I decode it to a byte[], and as A = {000000} and B = {000001}, I get [ {00000000} {00000000} {00000001} ].

The thing is that i want to count which bite is 1. In the case above, the bit that is 1 is the number 24, so i want to get 24.

So that is what I wanted to do:

EDITED WITH THE SOLUTION PROPOSED BY SCOTT:

using using System.Linq;

string stringData = "AAAB"; // {000000} {000000} {000000} {000001}
byte[] byteData = Convert.FromBase64String(stringData); // {00000000}{00000000}{00000001}
BitArray bitData = new BitArray(byteData.Reverse().ToArray()); // {100000000000000000000000}

 var i = bitData .Length;
 foreach (bool bit in bitData )
                        {
   if (bit)
   {
     //display i, the bit 1
   }
   j--;
 }

Thanks a lot, Scott!

Kane
  • 375
  • 1
  • 6
  • 18

3 Answers3

2

The easiest way to handle this is convert the byte[] in to a BitArray

string stringData = "AAAB"; // {000000} {000000} {000000} {000001}
byte[] byteData = Convert.FromBase64String(stringData); // {00000000}{00000000}{00000001}

BitArray bitData = new BitArray(byteData.Reverse().ToArray()); // {000000000000000000000001}


Console.WriteLine("byteData");
for(var i=0; i < byteData.Length; i++){ //bitData.Length is 32
    var bitValue = byteData[i];
    Console.WriteLine("{0} {1}", i, bitValue);
}

Console.WriteLine();
Console.WriteLine("bitData");
for(var i=0; i < bitData.Length; i++){ //bitData.Length is 32
    var bitValue = bitData[i];
    Console.WriteLine("{0} {1}", i, bitValue);
}

Run this example

Important note, i will start counting from the lest significant bit (the one currently 1) and go to the right. so your output will be true, false, ..., false, false not false, false ..., false, true. If you want it the other way throw another .Reverse().ToArray() on bitData.

Console.WriteLine();
Console.WriteLine("reversed");
var reversed = bitData.Cast<bool>().Reverse().ToArray();
for(var i=0; i < reversed.Length; i++){ //bitData.Length is 32
    var bitValue = reversed[i];
    Console.WriteLine("{0} {1}", i, bitValue);
}
Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
  • Scott thanks a lot or your answer! I tried it, but in the case of AAAB, inside the for(), returns true in the position 16 of the var i, not the position 23 (bitData.Length is 24 in this case). Would you know why? – Kane Aug 29 '14 at 04:49
  • Sorry about that, 32 was a typo of 23, for the order I did not notice the comment on the msdn for the constuctor *"The first byte in the array represents bits 0 through 7, the second byte represents bits 8 through 15, and so on. The Least Significant Bit of each byte represents the lowest index value"* I have updated my answer to show how to get it more like how you expect. – Scott Chamberlain Aug 29 '14 at 05:58
  • byteData does not have Reverse() function, because it is not an array. Is there another way to do it? – Kane Aug 29 '14 at 06:17
  • @Kane No it does not, but it is a `IEnumerable` so you can use `.Cast()` on it which gives you a `IEnumerable` which you can do a `.Reverse()` on (Be sure to include `using System.Linq;` at the top of your file to enable those extension methods). – Scott Chamberlain Aug 29 '14 at 06:19
1

I once wrote an Extension Method to allow getting and setting individual bits within a byte; maybe this will help you.

public static class MyExtensions
{
    /// <summary>
    /// Sets an individual bit inside a byte, based on the bit number.
    /// </summary>
    /// <param name="aByte">The byte where a bit is to be changed.</param>
    /// <param name="bitNumber">The bit number to read (between 0 and 7).</param>
    /// <param name="value">The value to set the bit to.  0/False or 1/True.</param>
    /// <returns>A byte with the requested bit changed.</returns>
    /// <remarks>The bit number must be between 0 and 7, otherwise an ArgumentOutOfRangeException is thrown.</remarks>
    public static byte SetBit(this byte aByte, byte bitNumber, bool value)
    {
        if (bitNumber > 7) { throw new ArgumentOutOfRangeException("bitNumber", "bitNumber was > 7"); }

        // create a mask of zeros except for the bit we want to modify
        byte mask = 1;
        mask = (byte)(mask << bitNumber);

        if (value)
        {
            // use bitwise-inclusive-or operator to make sure the bit equals 1 (and nothing else is changed)
            aByte = (byte)(aByte | mask);
        }
        else
        {
            // grab the inverse of our original mask (all ones except our bit equals zero)
            mask = (byte)(byte.MaxValue - mask);

            // use bitwise-and operator to make sure our bit equals 0 (and nothing else is changed)
            aByte = (byte)(aByte & mask);
        }
        return aByte;
    }


    /// <summary>
    /// Returns the value of an individual bit from within a byte.
    /// </summary>
    /// <param name="aByte">The byte from which to return bit data.</param>
    /// <param name="bitNumber">The bit number to read (between 0 and 7).</param>
    /// <returns>The value inside the requested bit.  0/False or 1/True.</returns>
    /// <remarks>The bit number must be between 0 and 7, otherwise an ArgumentOutOfRangeException is thrown.</remarks>
    public static bool GetBit(this byte aByte, byte bitNumber)
    {
        if (bitNumber > 7) { throw new ArgumentOutOfRangeException("bitNumber", "bitNumber was > 7"); }

        // create a mask of zeros except for the bit we want to modify
        byte mask = 1;
        mask = (byte)(mask << bitNumber);

        // use bitwise-and operator with our mask; if we get a 1, our bit must have also been a 1
        return (aByte & mask) > 0;
    }

}   

To use:

        byte b = 128;
        b = b.SetBit(1, true);

        bool b0 = b.GetBit(0); // false
        bool b1 = b.GetBit(1); // true, because we set it
        bool b2 = b.GetBit(2); // false
        bool b3 = b.GetBit(3); // false
        bool b4 = b.GetBit(4); // false
        bool b5 = b.GetBit(5); // false
        bool b6 = b.GetBit(6); // false
        bool b7 = b.GetBit(7); // true, because we started with 128
Sean Skelly
  • 1,229
  • 7
  • 13
0

Hope this helps.

        string stringData = "AAAB"; 
        byte[] byteData = Convert.FromBase64String(stringData); 
        StringBuilder sb = new StringBuilder("{");

        BitArray ba = new BitArray(byteData);
        for (int i = 0; i < ba.Length; i++)
        {
            sb.Append(ba[i] ? "1" : "0");    //append 1 if true, 0 if false.

            if (((i + 1) % 8 == 0) && ((i + 1) < ba.Length))  //adds formatting
                sb.Append("}{");
        }

        sb.Append("}");
        Console.Write("Bytes:" + sb.ToString());
        Console.Read(); //pause
neo
  • 161
  • 5