Sign in to follow this  
brwarner

Reading Bits from A file[Solved]

Recommended Posts

I am using the following code to extract at most 24 bits from a file:
	bool bits[25];
	int numBits = fread(&bits, sizeof(bool), 24, m_pFile);
	if(numBits <= 0) return E_FAIL;


The output for a txt file that contains the text "12" (without quotes) outputted 2 trues while a file containing "3414543" outputted 7 trues which doesn't make sense... does anyone know what is going on... Here is the open file code:
_set_fmode(_O_BINARY);
	if(fopen_s(&m_pFile, filename.c_str(), "r+") == 0)


[Edited by - brwarner on March 6, 2007 9:28:50 PM]

Share this post


Link to post
Share on other sites
You're reading bytes, not bits. sizeof(bool) is 1 meaning 1 byte, not 1 bit. You can't read a single bit.

To get bits you'll need to read bytes and shift around the bits & use masks & such to get the bit values.

-me

Share this post


Link to post
Share on other sites
bools take one byte of memory, they just can't be set to anything other than true(1) or false(0). The lowest form of memory a computer can address is 1 byte, you can not read individual bits.

If you want to read the first 24 bits in a file, read in 3 bytes and then use bitwise operaters on them to fill your bool array.

Share this post


Link to post
Share on other sites
Quote:
Original post by Scet
bools take one byte of memory, they just can't be set to anything other than true(1) or false(0). The lowest form of memory a computer can address is 1 byte, you can not read individual bits.

If you want to read the first 24 bits in a file, read in 3 bytes and then use bitwise operaters on them to fill your bool array.


Would this work:


BYTE bytes[3];
bool bits[24];
int numBytes = fread(&bytes, sizeof(BYTE), 3, m_pFile);
if(numBytes <= 0) return E_FAIL;
for(int i = 0; i < numBytes; i++)
{
for(int j = 0; j < 8; j++)
{
if(bytes[i] & j) m_bits.push_back(true);
else m_bits.push_back(false);
}
}
fclose(m_pFile);
return S_OK;





EDIT: I tested it and it seemed to work.

Share this post


Link to post
Share on other sites
Quote:
Original post by brwarner
Quote:
Original post by Scet
bools take one byte of memory, they just can't be set to anything other than true(1) or false(0). The lowest form of memory a computer can address is 1 byte, you can not read individual bits.

If you want to read the first 24 bits in a file, read in 3 bytes and then use bitwise operaters on them to fill your bool array.


Would this work:

*** Source Snippet Removed ***

EDIT: I tested it and it seemed to work.



NO, It should be doing something weird.

You need to have a seperate MASK variable (type BYTE) that in your 0..7 loop
starts as 1 (0x01) and then is shifted up 1 bit each itteration.
THAT is what you should be ANDing (&) with each byte you read in the outer loop.


MASK = MASK << 1;

Share this post


Link to post
Share on other sites
Thanks, it's working now but I'm having another problem...
When using fixed arrays:
BYTE bytes[4];
it works but when using:
BYTE* bytes = (BYTE*)malloc(4);
or
= (BYTE*)GlobalAlloc(GPTR, 4);
I get <Bad Ptr> from the fread call...
Some threads said it might be from previous data corruption but besides opening the file and initializing the vector class of bits there is basically nothing happening

EDIT: I am checking to make sure bytes != NULL and have tried = new BYTE[4] and still no luck
EDIT2: Nvm - I fixed it using pointers.

[Edited by - brwarner on March 6, 2007 9:05:38 PM]

Share this post


Link to post
Share on other sites
Umm... wow... what are you doing to my C++ :(

- We don't need anything platform-specific to read files. Oh, and there's also this totally new (if you call 9 years old new) I/O library in C++, called <iostream>, which tends to provide much better type safety, avoids messing around with pointers (because your stream is now represented by a class instance), doesn't require you to close things explicitly (in normal cases), uses flags to specify the file mode instead of a weird magic string, and doesn't have you worrying about distinguishing the size of a read-in thing from the number of things to read in. (BTW, for what you're doing, I don't see why you'd need an "r+" mode instead of just "r"... and like I said, nothing platform specific is needed - why not just have added a "b" to the magic string?)

- Keeping *any* kind of representation of a file stream as a data member of an object is usually a bad idea. Trust me on this one.

- There are nicer ways to indicate success or failure. If there is only one way to fail, then why not just use one of these 'bool's that you apparently know about? On the other hand, maybe it would do you some good to learn about exceptions, too... (I'll spare you for now, though).

- There should never be any need for a BYTE typedef. sizeof(char) is 1. By definition. Always.

- There are standard library containers that will automatically manage memory for you. In particular, std::vector carries pretty much an absolute minimum of overhead (in terms of both speed and size), and is quite a bit harder to mess up with (because you can just treat it like a local variable). Of course, there's no reason you'd ever use malloc() - or worse yet, a platform-specific memory allocation routine - in a *normal* C++ program, because 'new' and 'delete' do the job just fine. Of course, with the vector, you can avoid even worrying about that much.

Better yet, the std::vector is resizeable - it automatically wraps any sort of realloc() work you might have been thinking of doing - and the generated code will do basically just the same as anything you'd write yourself, because there's pretty much only the one way to do it.

- Please, don't *ever* write something like this again:


if(bytes[i] & j) m_bits.push_back(true);
else m_bits.push_back(false);


Consider which you would more likely say in English:

a) "Do I need an umbrella? Depends if it is raining."
b) "Do I need an umbrella? If it is raining, then yes; otherwise no."

Correspondingly, the proper way to write things is:


// the cast to bool here is optional depending on your usual style for
// interpreting integers in a boolean context. If you use it, it may be read as
// "whether".
m_bits.push_back(bool(bytes[i] & j));


Here, I show code to read an entire file into a vector of char (Vectors of bools are a bit sketchy; they're a specialized type that's designed to keep the bits packed together so they don't use a byte each, but that in turn means you can't address separate bits as array elements, because memory simply isn't bit-addressable.), and a helper function that picks a given bit value out of a vector of char. Note that passing the vector by reference avoids copying the data; it gives you the same efficiency that you are probably used to getting by passing things by pointer. But it also avoids having to deal with pointers.


// We will need:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

typedef std::vector<char> buffer;

bool readFile(buffer& destination) {
// Using an 'i'fstream implicitly sets the ios::in flag for the stream.
std::ifstream file(filename.c_str(), ios::binary);
if (!file.good()) {
// which is prettier than '== 0' or '!= 0'; but note that we can also
// use plain old 'if (file)', exactly as we could in C.
return false;
}
// We don't even have to do any iteration to read each byte of the file.
// And because the vector automatically resizes, we don't even have to
// determine the size of the file first.
typedef std::istreambuf_iterator<char> filePosition;
std::copy(filePosition(file), filePosition(),
std::back_inserter<char>(destination));
return true;
}

bool getBit(const buffer& data, int position) {
char c = data[position / CHAR_BITS];
// You might need to modify this depending on your interpretation of the
// "bit-endianness".
return bool(c & (1 << (position % CHAR_BITS)));
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this