Reading a file bit by bit

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
 
H

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);
}
 
C

christery

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).
 
C

christery

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...
 
H

Heandel

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
 
I

Ignacio Machin ( .NET/ C# MVP )

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){
}
 
C

Cor Ligthert[MVP]

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
 
E

Ertugrul Söylemez

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.
 
H

Heandel

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
 
E

Ertugrul Söylemez

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top