C++ reading binary files

生来就可爱ヽ(ⅴ<●) 提交于 2021-02-10 06:03:23

问题


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.


回答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!



回答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.




回答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");
    }
}


来源:https://stackoverflow.com/questions/43765881/c-reading-binary-files

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!