简体   繁体   中英

C++ reading binary files

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? Ps 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.

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!

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 .

Based on Pavel answer, you can also add this to see the data in real binary, namely 0 's and 1 s. 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");
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM