0

I'm trying to read a binary file to get its individual bit values. I'm doing so using the following function.

string readFileBytes(const char *name)
{
  ifstream fl(name);
  fl.seekg( 0, ios::end );
  size_t len = fl.tellg();
  char *ret = new char[len+1];    

  fl.seekg(0, ios::beg); 
  fl.read(ret, len);
  fl.close();    
  ret[len] = '\0';

  return ret;
  delete ret;
       }

This works fine. For the next part I'm taking each element of the array ret and using the following function I wrote to get the individual bit values.

string out;
for (int i=0; i < len; i++)
{


    for (int x =7; x >=0; x--)
    {
    out += ((ret[i]>>x) & 0x01);
    }       
}

If I have cout << ((ret[i]>>x) & 0x01); within the nested loop instead it prints the bit values perfectly. But when I have it as it is, and print the string (out), I get nothing but smiley faces.

Any ideas why?

azhamn
  • 64
  • 1
  • 7
  • at least the operating system is being nice to you with the smiley faces, my machine just boringly displays `NUL` `SOH` `NUL` `NUL`... – vsoftco Apr 05 '15 at 23:40

3 Answers3

3

The expression

((ret[i]>>x) & 0x01)

evaluates to the integer 0 or 1 (i.e., numerical values of 0 or 1). You need the character representing 0 and 1. Try

out += '0' + ((ret[i]>>x) & 0x01);

Related: Convert an int to ASCII character

Community
  • 1
  • 1
vsoftco
  • 55,410
  • 12
  • 139
  • 252
1

A binary 0 or 1 does not produce a char '0' or '1'. You need to put proper char codes into the output string.

ScottMcP-MVP
  • 10,337
  • 2
  • 15
  • 15
1

return ret;delete ret; This is wrong as well. Are there any warnings ? You are having delete after return.
If you are deleting a char* then you should use delete[] instead of delete.

Jagannath
  • 3,995
  • 26
  • 30
  • OP probably shouldn't even be using char* anyways, `string` would more than likely suffice for this – Alejandro Apr 05 '15 at 23:31
  • @Alejandro probably he's using `char*` for the buffer passed to `ifstream::read`, then returning it as a `std::string` due to `std::string` implicit constructor that takes a `char*`. The problem is the memory leak, which can be avoiding by using `std::unique_ptr ret(new char[len+1]);` instead. – vsoftco Apr 05 '15 at 23:39
  • @Alejandro and then using it with `ret.get()` where a the raw pointer is needed. – vsoftco Apr 05 '15 at 23:52
  • @Alejandro I'm using the char* because it's needed by ifstream. – azhamn Apr 06 '15 at 01:16
  • @vsoftco doesn't the `ret[len] = '\0'` deal with the potential memory leak issue? – azhamn Apr 06 '15 at 01:17
  • @nappyboi, no, at the end of the program (or if you invoke `readFileBytes(...)` multiple times) the memory allocated for `ret*` is not released. – vsoftco Apr 06 '15 at 01:19
  • @nappyboi `ifstream` can be used with `std::getline` which works with `std::string` – Alejandro Apr 06 '15 at 01:38
  • @Alejandro True. But wouldn't that ignore any bits that represent the a new line(`\n`), since `getline` uses this as the delimiter? In my case I need to read those bits too, so I went with `ifstream::read` – azhamn Apr 06 '15 at 15:32