最好的方法是读取和比较C ++中二进制文件的字节数据吗?

时间:2015-12-15 18:59:02

标签: c++ parsing io byte

我无法理解如何使用char数组(std :: ifstream.read()的第一个参数来比较不同类型的数据)。

例如,如果我试图阅读Windows PE文件的魔力,我这样做但我觉得有更好的方法围绕它,因为据我所知,这需要我定义每个预先假设的值file作为std :: array:

std::array<char, 2> magic;
in.read(magic.data(), magic.size());
std::array<char, 2> shouldBe = { 0x4d, 0x5a }; // MZ for dos header

if(magic == shouldBe) {
    // magic correct
}

这给了我编译器警告,例如从int到char的无效转换。 我也不太清楚我是如何读取其他十六进制值与ASCII字符完全相关的文件的神奇之处。 例如,每个Java类文件都以0xCAFEBABE开头是一个神奇的但是当我以4个字符读取它然后将每个部分转换为int时,我得到了我不想要的填充。

char* magic = new char[4];
in.read(magic, 4);
// how can I compare this array to 0xCAFEBABE?

当我遍历每个部分然后转换为int并在输出流中使用std :: hex时输出:

ffffffca fffffffe ffffffba ffffffbe

解析PE文件和Java类等二进制文件格式中使用的大量不同类型值的最佳方法是什么?

2 个答案:

答案 0 :(得分:3)

这种方法非常好。唯一的问题是这一行:

std::array<char, 2> shouldBe = { 0x4d, 0x5a }; // MZ for dos header

列表初始化不允许缩小转换,因此您只需要进行一些显式转换:

std::array<char, 2> shouldBe = { (char)0x4d, (char)0x5a };

答案 1 :(得分:1)

您基本上有两种选择:您可以将值硬编码到程序中,也可以将它们存储在外部。如果你在内部存储它们,那么通过稍微构建数据可能最容易开始:

struct magic { 
    std::string value;
    int result;
};

std::vector<magic> values { 
    { ".ELF", 1 },
    { "MZ", 2},
    { "\xca\xfe\xba\xbe", 3}, // 0xcafebabe
    { "etc", -1}};

然后你可以(例如)在循环中逐步执行值,比较值,当你得到匹配时有一个值告诉你(例如)如何处理那种文件。

如果您将值存储为我在此处所做的字符串,那么将字符串进行比较可能也是最简单的。一种显而易见的方法是从文件的开头读取一个块(例如,2千字节),然后从文件中的正确字节数创建一个字符串,然后与预期值进行比较。