C 读取二进制文件

C++ reading binary files

本文关键字:二进制文件 读取      更新时间:2023-10-16

我想了解读取二进制文件在C 中的工作方式。我的代码:

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;
}

我以为,如果我cout我的缓冲区,我会以二进制的方式得到结果。

My output is: ˙Ř˙á6Exif

,如果我读取文本文件,它将以普通形式显示不在二进制中的文本。显然,我的逻辑不在这里。如何将文件读取到缓冲区中,以包含二进制值?P.S.我是为实施Shannon-Fano算法而这样做的,因此,如果有人对阅读二进制文件有任何建议,我会很感激。

您需要调整矢量大小,而不是保留:

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 '' ond-of-string terminator
}

否则,您的代码将尝试将size字符读取为空缓冲区。您还可以使用设置向量大小的向量构造函数:vector<char> buffer(size);

您可以这样输出缓冲区的字节值:

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

或类似常见的十六进制编辑器为十六进制输出所做的事情:

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] = '';
        }
        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);
}

带有" Hello World!"的缓冲区缓冲区数据将打印如下:

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

基于pavel的答案,您还可以添加此信息以在真实二进制中查看数据,即 0 s and 1 s。不要忘记包含BITSET标题。

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

在二进制模式下打开文件意味着您的操作系统不会在CR/LF/CRLF格式之间透明地转换线结尾。

在七行之后,它对您的计算机打印字符串的方式根本没有任何影响。我不知道"获得二进制的结果"是什么意思,但是我建议通过在其十六进制表示中一次打印其构成字节来呈现vector<char>的内容:

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

输出看起来像:

0123456789abcdef0123456789abcdef

使用base-16(或" HEX"(数值系统,每两个字符代表数据中字节的0-255字节值。这是非文本信息的常见表示。

另外,您可以在基本-2中输出数据(字面上是"二进制"(。

由您决定如何提供信息。文件打开模式与您的向量无关。

您还需要修复向量的大小;目前,当您含义.resize时,您致电.reserve