Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write/read bits from/to a Stream? (C#)

Tags:

c#

How can I write bits to a stream (System.IO.Stream) or read in C#? thanks.

like image 968
Alon Gubkin Avatar asked Aug 22 '09 12:08

Alon Gubkin


2 Answers

You could create an extension method on Stream that enumerates the bits, like this:

public static class StreamExtensions
{
    public static IEnumerable<bool> ReadBits(this Stream input)
    {
        if (input == null) throw new ArgumentNullException("input");
        if (!input.CanRead) throw new ArgumentException("Cannot read from input", "input");
        return ReadBitsCore(input);
    }

    private static IEnumerable<bool> ReadBitsCore(Stream input)
    {
        int readByte;
        while((readByte = input.ReadByte()) >= 0)
        {
            for(int i = 7; i >= 0; i--)
                yield return ((readByte >> i) & 1) == 1;
        }
    }
}

Using this extension method is easy:

foreach(bool bit in stream.ReadBits())
{
    // do something with the bit
}

Attention: you should not call ReadBits multiple times on the same Stream, otherwise the subsequent calls will forget the current bit position and will just start reading the next byte.

like image 63
Tommy Carlier Avatar answered Oct 01 '22 19:10

Tommy Carlier


This is not possible with the default stream class. The C# (BCL) Stream class operates on the granularity of bytes at it's lowest level. What you can do is write a wrapper class which reads bytes and partititions them out to bits.

For example:

class BitStream : IDisposable {
  private Stream m__stream;
  private byte? m_current;
  private int m_index;
  public byte ReadNextBit() { 
    if ( !m_current.HasValue ) {
      m_current = ReadNextByte();
      m_index = 0;
    }
    var value = (m_byte.Value >> m_index) & 0x1;
    m_index++;
    if (m_index == 8) {
      m_current = null;
    }
    return value;
  }
  private byte ReadNextByte() {
    ...
  }
  // Dispose implementation omitted
}

Note: This will read the bits in right to left fashion which may or may not be what you're intending.

like image 33
JaredPar Avatar answered Oct 01 '22 21:10

JaredPar