Reputation: 377
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!
Upvotes: 1
Views: 2492
Reputation: 127543
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);
}
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);
}
Upvotes: 2
Reputation: 161
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
Upvotes: 0
Reputation: 1324
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
Upvotes: 1