首页 > 解决方案 > 从二进制文件读取时 C++ 跳过字节

问题描述

我整理了一些 C++ 代码来从某些文件中提取 PNG。它不是最精致的,但它似乎跳过了某些空字节。

这是代码:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
    ifstream source("source.win", ios::out | ios::binary);
    char current[] = { 0,0,0,0 };
    char header[] = { (char)137, 'P', 'N', 'G' };
    char footer[] = { 'I', 'E', 'N', 'D' };
    char c = 0;
    int n = 0;
    ofstream out("png0.png", ios::out | ios::binary);
    out.close();
    while (source >> c) {
        if (out.is_open()) {
            out << c;
        }
        current[0] = current[1];
        current[1] = current[2];
        current[2] = current[3];
        current[3] = c;
        if (current[0] == (char)137 &&
            current[1] == 'P' &&
            current[2] == 'N' &&
            current[3] == 'G') {
            n++;
            out.open("png" + to_string(n) + ".png", 6);
            out << (char)137 << "PNG";
        }
        if (current[0] == 'I' &&
            current[1] == 'E' &&
            current[2] == 'N' &&
            current[3] == 'D') {
            out.close();
        }
    }
}

这是它输出的文件的开头,以及它应该输出的实际文件的开头:

89 50 4E 47 1A 00 00 00 49 48 44 52 00 00 01 00
00 00 01 00 08 06 00 00 00 5C 72 A8 66 00 00 5F
49 44 41 54 78 9C ED DD 6F 88 65 75 ...

对比

89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52
00 00 01 00 00 00 01 00 08 06 00 00 00 5C 72 A8
66 00 00 0A 5F 49 44 41 54 78 9C ED DD 6F 88 65
75 ...

编辑:我从 >> 切换到 get() 并从 << 切换到 put(),但0A仍然被放置为0D 0A

标签: c++iobinaryfiles

解决方案


该程序不会删除空值,而是删除空白字符。这是因为 的默认行为operator>>是丢弃空格。注意0As(换行)和0Ds(回车)是如何被去掉的。您还应该发现20(空格)、0C(换页)、09(制表符)和 08(垂直制表符)也不见了。

hack 修复是添加std::noskipws(ie source >> std::noskipws >> c) 以指示流不跳过空格。但更好的方法是首先不要进行格式化读写,std::istream::get()而是更喜欢std::ostream::put()

也就是说,一旦您找到感兴趣区域的开始,您应该考虑一次切换到std::istream::read()std::ostream::write()移动多个字节的整个块。


推荐阅读