0

I have a binary file. i am reading 16 bytes at a time it using fstream.

I want to convert it to an integer. I tried atoi. but it didnt work. In python we can do that by converting to byte stream using stringobtained.encode('utf-8') and then converting it to int using int(bytestring.hex(),16). Should we follow such an elloborate steps as done in python or is there a way to convert it directly?

ifstream file(binfile, ios::in | ios::binary | ios::ate);
if (file.is_open())
{

    size = file.tellg();
    memblock = new char[size];
    file.seekg(0, ios::beg);
    while (!file.eof())
    {
        file.read(memblock, 16);            
        int a = atoi(memblock); // doesnt work 0 always
        cout << a << "\n";
        memset(memblock, 0, sizeof(memblock));
    }
    file.close();

Edit:

This is the sample contents of the file.

53 51 4C 69 74 65 20 66 6F 72 6D 61 74 20 33 00
04 00 01 01 00 40 20 20 00 00 05 A3 00 00 00 47
00 00 00 2E 00 00 00 3B 00 00 00 04 00 00 00 01

I need to read it as 16 byte i.e. 32 hex digits at a time.(i.e. one row in the sample file content) and convert it to integer. so when reading 53 51 4C 69 74 65 20 66 6F 72 6D 61 74 20 33 00, i should get, 110748049513798795666017677735771517696

But i couldnt do it. I always get 0 even after trying strtoull. Am i reading the file wrong, or what am i missing.

10
  • 4
    atoi() converts a null terminated text string to an integer. Unless your 16 bytes all have the last byte set to '\0', and the previous fifteen bytes consist of leading whitespace, an optional minus sign, and at least one more character between '0' and '9', then atoi() will not work, because that's what it does, and the only thing that it does (technically, the '\0' doesn't have to be the last byte, but that's not a relevant detail). Commented Jan 7, 2019 at 16:13
  • 1
    An int is typically 4 bytes, which can't store a 16 byte value. Commented Jan 7, 2019 at 16:14
  • Like this? stackoverflow.com/q/1070497 Commented Jan 7, 2019 at 16:14
  • 1
    size = file.tellg(); I believe this should return 0 since the file was just opened. Also, sizeof(memblock) will return the size of the pointer, not the length of the buffer. Commented Jan 7, 2019 at 16:21
  • 1
    @JohnnyMopp I though the same thing until I looked up what ios::ate does. That part of the code is fine. Commented Jan 8, 2019 at 4:23

2 Answers 2

1

You have a number of problems here. First is that C++ doesn't have a standard 128-bit integer type. You may be able to find a compiler extension, see for example Is there a 128 bit integer in gcc? or Is there a 128 bit integer in C++?.

Second is that you're trying to decode raw bytes instead of a character string. atoi will stop at the first non-digit character it runs into, which 246 times out of 256 will be the very first byte, thus it returns zero. If you're very unlucky you will read 16 valid digits and atoi will start reading uninitialized memory, leading to undefined behavior.

You don't need atoi anyway, your problem is much simpler than that. You just need to assemble 16 bytes into an integer, which can be done with shifting and or operators. The only complication is that read wants a char type which will probably be signed, and you need unsigned bytes.

ifstream file(binfile, ios::in | ios::binary);
char memblock[16];
while (file.read(memblock, 16))
{
    uint128_t a = 0;
    for (int i = 0; i < 16; ++i)
    {
        a = (a << 8) | (static_cast<unsigned int>(memblock[i]) & 0xff);
    }
    cout << a << "\n";
}
file.close();
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the idea. But neither uint128_t not unsigned __int128 worked for me. As i am using MS VSC++ compiler. But i used you way and read 4 bytes at a time and stored in a string used bitset to concatenate those strings to form 128bit binary equivalent of the 16byte hex value. As of now i am using that value and right shifting , so i need not store the resultant 128 bit binary string. But any idea on how to use unsigned __128 in vsc++? It would save a lot of time
@Prakrithi according to this there is no way with VSC++ at this time. I just did a search through the libraries in VS2017 and can confirm.
0

It the number is binary what you want is:

    short value ;
    file.read(&value, sizeof (value));            

Depending upon how the file was written and your processor, you may have to reverse the bytes in value using bit operations.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.