1
\$\begingroup\$

The way I am using this method assumes all data is byte-aligned, so I don't really care about the rest of the bits.

This method is written in an extension of BinaryReader which provides more methods when I'm reading binary data from files. The BinaryReader provided does not appear to support reading bits.

Is there a better way I could write this method? Also I'm not sure if there's a more direct way to build a bitmask so I did it the long way.

/* Returns the value of the first n bits. */
public byte ReadBits(byte n)
{
 byte val = base.ReadByte();
 byte sum = 0;
 for (int i = 0; i < n; i++)
 sum += (byte)(val & (1 << i));
 return sum;
}

I am using .NET 3.5

asked Aug 15, 2012 at 21:42
\$\endgroup\$
4
  • \$\begingroup\$ I don't think so. For example you read 4 bits and it tells the length of the following data. I'd want it as an int or a byte. \$\endgroup\$ Commented Aug 15, 2012 at 22:30
  • \$\begingroup\$ It is similar to ReadInt32 or ReadByte: just return a single value that is represented by the bytes that were read. Or in this case, bits. I have not thought about the case where there is no byte alignment, but adobe's SWF format is always byte-aligned. \$\endgroup\$ Commented Aug 15, 2012 at 22:55
  • \$\begingroup\$ Oh, I should probably mention that this particular method is written in an extension of BinaryReader, which is why it explicitly reads bytes as the first line rather than taking a stream of bytes. \$\endgroup\$ Commented Aug 15, 2012 at 23:00
  • \$\begingroup\$ That would be an appropriate method for the BitConverter, where it takes some input and returns a converted value. However I think since I just need to read n bits and ignore the rest, it would be fastest to just do the operation in one call rather than making the extra conversion afterwards. \$\endgroup\$ Commented Aug 15, 2012 at 23:15

1 Answer 1

3
\$\begingroup\$

I have not tested this that well. If anyone finds a bug, please let me know.

// Throws away the unused bits
public byte ReadFirstNBits(int n)
{
 Contract.Requires(n >= 0 && n <= 8, "Code contract may be too slow for your needs");
 byte val = base.ReadByte();
 return val >> (8 - n);
}
// Throws away the unused bits
public byte ReadLastNBits(int n)
{
 Contract.Requires(n >= 0 && n <= 8, "Code contract may be too slow for your needs");
 byte val = base.ReadByte();
 byte mask = (byte)((1 << n) - 1);
 return val & mask;
}

You can try this for yourself if you have a Python prompt:

>>> a = 0b11001001 
>>> a
201
>>> a >> 4
12
>>> a >> 5
6
>>> a >> 3
25
>>> a >> 6
3
>>> a >> 2
>>> for i in range(8): print bin(a >> i)
0b11001001
0b1100100
0b110010
0b11001
0b1100
0b110
0b11
0b1
>>> 
answered Aug 15, 2012 at 22:21
\$\endgroup\$
4
  • \$\begingroup\$ Bit-shifting has always been a mystery to me. I was reading this stackoverflow.com/a/141873/536607 and it sort of gives me a better idea and can understand why shifting would work for this problem. Hopefully it will come to mind immediately when working with bit operations. \$\endgroup\$ Commented Aug 15, 2012 at 23:31
  • \$\begingroup\$ Well, I am glad this was helpful. \$\endgroup\$ Commented Aug 16, 2012 at 15:57
  • \$\begingroup\$ >= 0 && <= 8 shouldn't it be >= 0 && < 8? \$\endgroup\$ Commented Aug 16, 2012 at 16:23
  • \$\begingroup\$ @luiscubal, you could chose to read the entire byte, which is 8 bits long, in which case val >> 0 should just give you val. It is not as fast as simply calling base.ReadByte(), but it works correctly. The number of bits to read could be stored in a variable. I find the case where you wish to read 0 bits more ridiculous, but ... the computers do not necessarily do what you meant; only what you told them. \$\endgroup\$ Commented Aug 16, 2012 at 16:55

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.