C++ reading binary files

14,282

Solution 1

You need to resize your vector, not reserve it:

int main()
{
    ifstream ifd("input.png", ios::binary | ios::ate);
    int size = ifd.tellg();
    ifd.seekg(0, ios::beg);
    vector<char> buffer;
    buffer.resize(size); // << resize not reserve
    ifd.read(buffer.data(), size);

    cout.write(buffer.data(), buffer.size()); // you cannot just output buffer to cout as the buffer won't have '\0' ond-of-string terminator
}

Otherwise your code tries to read size characters into an empty buffer. You may as well use vector constructor that sets vector size: vector<char> buffer(size);

You can output byte values of your buffer this way:

void dumpbytes(const vector<char>& v)
{
    for (int i=0; i<v.size(); ++i)
    {
        printf("%u ", (unsigned char)v[i]);
        if ((i+1) % 16 == 0)
            printf("\n");
    }
    printf("\n");
}

Or something like common hex editors do for hex output:

void dumphex(const vector<char>& v)
{
    const int N = 16;
    const char hex[] = "0123456789ABCDEF";
    char buf[N*4+5+2];
    for (int i = 0; i < v.size(); ++i)
    {
        int n = i % N;
        if (n == 0)
        {
            if (i)
                puts(buf);
            memset(buf, 0x20, sizeof(buf));
            buf[sizeof(buf) - 2] = '\n';
            buf[sizeof(buf) - 1] = '\0';
        }
        unsigned char c = (unsigned char)v[i];
        buf[n*3+0] = hex[c / 16];
        buf[n*3+1] = hex[c % 16];
        buf[3*N+5+n] = (c>=' ' && c<='~') ? c : '.';
    }
    puts(buf);
}

Buffer with "Hello World!" data would be printed as follows:

48 65 6C 6C 6F 20 57 6F 72 6C 64 21                  Hello World!

Solution 2

Opening a file in binary mode means that your operating system won't transparently translate line endings between the CR/LF/CRLF formats.

It doesn't have any effect at all on how your computer prints a string, seven lines later. I don't know what "get the result in binary" means, but I suggest rendering the contents of your vector<char> by printing its constituent bytes, one at a time, in their hex-pair representation:

std::cout << std::hex << std::setfill('0');
for (const auto byte : buffer)
   std::setw(2) << byte;

The output will look something like:

0123456789abcdef0123456789abcdef

Every two characters represents the 0-255 byte value of a byte in your data, using the base-16 (or "hex") numerical system. This is a common representation of non-text information.

Alternatively, you could output the data in base-2 (literally "binary").

It's up to you how to present the information. The file open mode has nothing to do with your vector.

You also need to fix your vector's size; at the moment you call .reserve when you meant .resize.

Solution 3

Based on Pavel answer, you can also add this to see the data in real binary, namely 0's and 1s. do not forget to include the bitset header.

void dumpbin(const vector<char>& v)
{
    for (int i = 0; i < v.size(); ++i)
    {
        cout <<bitset<8>((unsigned char)(v[i])) << " ";
        if ((i + 1) % 8 == 0)
            printf("\n");
    }
}
Share:
14,282
mrNobody
Author by

mrNobody

Updated on July 28, 2022

Comments

  • mrNobody
    mrNobody almost 2 years

    I want to understand how does reading binary files work in C++. My code:

    int main() {
        ifstream ifd("input.png",ios::binary |ios::ate);
        int size = ifd.tellg();
        ifd.seekg(0,  ios::beg);
        vector<char> buffer;
        buffer.reserve(size);
        ifd.read(buffer.data(), size);
    
        cout << buffer.data();
        return 0;
    }
    

    I thought that if I cout my buffer I would get the result in binary but that is not the case.

    My output is: ˙Ř˙á6Exif

    And if I read the text file it displays the text in normal form not in binary. Obviously my logic is not right here. How can I read files to a buffer so it will contain binary values? P.s. I`m doing this for implementing a Shannon-Fano algorithm so if anyone has any advice on reading a binary file I would be grateful.