Reading a file bit by bit

  • Thread starter Thread starter Heandel
  • Start date Start date
H

Heandel

Hello,

I need to read a file bit by bit, but the lowest level .NET allows me is
byte by byte.
Is there anyway i can read a bit ? Or convert the bytes in bits ?

Thank you,

Heandel
 
I haven't found anything about converting from byte to bit so i wrote this :
Maybe it's not really optimized but it works...


bool[] bits = new bool[8];
BinaryReader br = new BinaryReader(File.Open("file.bin", FileMode.Open));

while (br.PeekChar() != -1)
{
byte b = br.ReadByte();

// Compare to powers of 2
for (byte i = 0; i <= 7; i++) bits = (((b & 1 << i) > 0) ? true :
false);
}
 
Is there anyway i can read a bit ? Or convert the bytes in bits ?

To pick a bit out of a byte can be using the "and" (some & or && there
is a "bit" of a differance ;) ) might be correct with hex F0 (128) for
the higest and 01 (1) as the lowest dec is 2,4,8,16,32,64 in an 8
bit, but why... (?)
Never did bit picking in C#, only C... and yeah, one operator is
bitwise, the other is logical (In C).
 
Actually i found the solution a few minutes after posting...

Just as usual...

Yeah, so to tell...

using System;


namespace Slask
{
class Slask
{

static void Main(string[] args)
{

{
int slask = 31;
Console.WriteLine(slask & 1);
Console.WriteLine(slask & 2);
Console.WriteLine(slask & 4);
Console.WriteLine(slask & 8);
Console.WriteLine(slask & 16);
Console.WriteLine(slask & 32);
Console.WriteLine("------------");



slask = 32;
Console.WriteLine(slask & 1);
Console.WriteLine(slask & 2);
Console.WriteLine(slask & 4);
Console.WriteLine(slask & 8);
Console.WriteLine(slask & 16);
Console.WriteLine(slask & 32);
}
Console.Read();
}

}
}


Just how it works, nah... shouldnt do that... Heh...
 
I wouldn't use BinaryReader; if you use FileStream, then you can get
end-of-stream information without "peeking" and without the need to seek
the stream for every operation (the call to PeekChar() implicitly seeks
the stream, and of course you're not really dealing with characters
anyway, so the PeekChar() method can easily cause incorrect results...you
might wind up missing the last bytes in the file if they don't compose an
actual valid character in the encoding for your BinaryReader).

I changed this, thank you :)
There is also never any need for an expression of the form "(X) ? true :
false"; you can always just use "(X)" instead.

The true : false was previously a 1 : 0 to help me debug. I removed it now,
thanks !
And while the bit shift operator has precedence over the logical AND
operator, I would still make the code explicit just for readability: "(b &
(1 << i)) > 0".

True but this is a question of style ;)
I'm not sure it's a lot more readable.
There is, of course, the question of whether creating an array of eight
bools is really the appropriate way to go. Your processing can be much
more efficient if you are able to use each bit directly rather than
caching them one byte at a time (after all, by caching them one byte at a
time, you have basically just recreated the original data and the
associated processing requirements, just in a less efficient way).

The array of eight bools is just a sample to see how it works. In fact, I
will need (huge) multidimensional arrays, of almost arbitrary lenght. There
will be no caching at all, just raw bits everywhere.
I just recreated the byte system for the debugging purposes.

If you want to abstract the bitstream, it might be better to just cache
the original byte, and return one bool at a time from a ReadBit() method
(wrapping the whole thing in a simple "reader" class, of course).

Yes, this is what I'm going to do !
All that and a couple of other stylistic differences, and that's pretty
much the code I'd have written given the specific behavior you seem to
want. :)

Pete

Thanks for your help Pete ! :)

Heandel
 
Hello,

I need to read a file bit by bit, but the lowest level .NET allows me is
byte by byte.
Is there anyway i can read a bit ? Or convert the bytes in bits ?

Thank you,

Heandel

the lowest you can get is a byte, not only at C# level but even at
assembly level.

you have to read one byte (I advise you to read more though) and yield
the value as needed

you could do something like:

enum BitValue {One, Zero};

IEnumerable<BitValue> GetBits(){

foreach(byte b in ReadBuffer()){
byte mask = 1;
while(mask<250){
if (b & mask == 0 )
yield BitValue.Zero;
else
yield BitValue.One;
mask = mask*2;
}
}

}

byte[] ReadBuffer( int size){
}
 
Like "you" cannot read this message point by point, not any computer can
read a file bit by bit. It is not even stored in bytes but always in
segments from n bytes.

Cor
 
Cor said:
Like "you" cannot read this message point by point, not any computer can
read a file bit by bit. It is not even stored in bytes but always in
segments from n bytes.

That comparison doesn't make sense. A computer can well read bit by
bit. It just doesn't. This is not related to some cognitive
limitation, but just to performance, since individual bits are seldomly
needed anyway.


Greets,
Ertugrul.
 
My code works pretty fine but is actually quite slow... I get around 4500
bits read per millisecond on my machine.

Here is the loop I use :

FileStream fs = File.Open("file.bin", FileMode.Open);

byte b = new byte();
bool[] bits = new bool[fs.Length * 8];

for (ulong i = 0; fs.Position < fs.Length; i += 8)
{
b = (byte)fs.ReadByte();
for (byte j = 0; j <= 7; j++) bits[i + j] = ((b & (1 << (7 -
j))) > 0);
}

I have found that replacing the b in the second for and removing the b =
(byte)fs.ReadByte(); speeds up the loop by 10x aprox, but the results I get
from the & operation are completely wrong.

Any idea ? Or maybe this algorithm can't be improved ?

Thank you,

Heandel
 
Heandel said:
My code works pretty fine but is actually quite slow... I get around 4500
bits read per millisecond on my machine.

Here is the loop I use :

FileStream fs = File.Open("file.bin", FileMode.Open);

byte b = new byte();
bool[] bits = new bool[fs.Length * 8];

for (ulong i = 0; fs.Position < fs.Length; i += 8)
{
b = (byte)fs.ReadByte();
for (byte j = 0; j <= 7; j++) bits[i + j] = ((b & (1 << (7 -
j))) > 0);
}

I have found that replacing the b in the second for and removing the b =
(byte)fs.ReadByte(); speeds up the loop by 10x aprox, but the results I get
from the & operation are completely wrong.

Any idea ? Or maybe this algorithm can't be improved ?

You algorithm uses a lot of computation time. Instead read in large
blocks, then split to bits virtually:

byte[] bytes;

getBit(n) = bytes[n >> 3] & (1 << (n & 7)) != 0;


Greets,
Ertugrul.
 
Back
Top