2

This is my first post so sorry if I break any unwritten rules. :P I am a beginner/intermediate programmer and I need help with this program.

I am trying to infile/read/ifstream (whatever) a .dat file as HEX into one big string.

I don't want to read it as text. I want the hex format so I can search through the string and make changes to it. (Like an automatic hex editor)

ex. my file "00000000.dat" is ~7kb in size.

In hex editor, the hex look like this:

0A 00 00 0A 00 05 4C 65 76 65 6C 07 00 06 42 6C 6F 63 6B 73 00 00 80 00 07 FF 39
01 FF 03 03 02 FF 3F 00 07 FF 39 01 FF 03 03 02 FF 3F 00 07 FF 39 01 FF 03 03 02
FF 3F 00 07 FF 39 01 FF 03 03 02 FF 3F 00 07 FF 39 01 FF 03 03 02 FF 3F 00 07 FF
39 01 FF 03 03 02 FF 3F 00 07 FF 39 01 FF 03 03 02 FF 3F 00 07 FF 39 01 FF 03 03
02 FF 3F 00..... for a while...

I need all of it in a string variable (with no spaces preferably).

My current code sucks and for now only prints the result. (got it from ehow) and seems to pick and choose what it wants to input/print.

#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>
#include <fstream>

using namespace std;

int main()
{
    ifstream input;
    input.open("00000000.dat");

    unsigned char h1,h2;

    do
    {
        input >> h1;
        cout << hex << (unsigned int)h1;
        input >> h2;
        cout << hex << (unsigned int)h2;
    }while(!input.eof());

cin.get();
return 0;
}

It's a big file so I can't show yo what it prints, but it is missing some bytes. (ex "0A 00 00 0A 00 05....." prints as "00 05.....") this is true for the ending as well.

Sorry if I didn't explain it well :(

mrg95
  • 2,371
  • 11
  • 46
  • 89

2 Answers2

8

You should open the stream as binary, as mentioned. You can use the regular >> operator if you tell it not to skip white space.

unsigned char x;
std::ifstream input("00000000.dat", std::ios::binary);
input >> std::noskipws;
while (input >> x) {
    std::cout << std::hex << std::setw(2) << std::setfill('0')
              << (int)x;
}

To get the content into a string, you can use an ostringstream instead of cout.

jxh
  • 69,070
  • 8
  • 110
  • 193
0

You want to open the file to read as binary. You're reading as text right now. So it should look like

//Open file object to read as binary
std::ifstream input("00000000.dat", std::ios::in | std::ios::binary);    

You also might want to use reinterpret_cast to read one byte at a time (i.e. can't figure out what you want -- your code and your description are doing opposite things).

//Read until end of file
while(!input.eof())    
{

    //Or .good() if you're paranoid about using eof()

    //Read file one byte at a time
    input.read(reinterpret_cast<char *>(&h1), sizeof(unsigned char));

}

Or if you just want everything in one string, why not just declare a string and read it into that?

MrPickle5
  • 522
  • 4
  • 9
  • 31
  • IIRC testing on eof in the loop condition is also error-prone. You might run into the eof after reading `h1` so `h2` could not have been updated. Better like `while(input >> h1) { /* use only h1 */ }` though we need to use unformatted input functions here. – dyp May 07 '13 at 03:12
  • `input.get( reinterpret_cast(h1) );` should also be possible instead of using `read`. – dyp May 07 '13 at 03:15
  • I put the eof() warning in my comments and still get responses like these. :( eof() has never failed on me, but like I said -- you can always use .good(). – MrPickle5 May 07 '13 at 03:16
  • There's a famous example how to read a whole file into a string (updated for C++11): `std::string str{ std::istreambuf_iterator{input}, std::istreambuf_iterator{} };` (yes, one line) – dyp May 07 '13 at 03:18
  • IIRC `eof` is not a problem if you only use one variable and don't care about `good`. OP's using two different variables here, and the eof could occur between reading `h1` and `h2`. – dyp May 07 '13 at 03:19
  • Your example is missing a lot of definitions (`byteArray`, `stringArray`, `numberOfBytes`). It's also "very slow" as you only increase the size of the `*input` array by 1 each iteration and only read 1 byte per iteration which is missing the point of `read` having a second parameter. – dyp May 07 '13 at 03:26
  • Thank you all for the speedy replies. I will test things out and get back to you soon. :) – mrg95 May 07 '13 at 03:36