有人能指出我如何读取由C结构定义的二进制文件的正确方向吗? 它在结构体内部有一些#define,这使我的事情变得复杂 结构看起来像这样:(虽然它比它更大,更复杂)
struct Format {
unsigned long str_totalstrings;
unsigned long str_name;
#define STR_ORDERED 0x2
#define STR_ROT13 0x4
unsigned char stuff[4];
#define str_delimiter stuff[0]
}
如果有人能指出我如何做到这一点,我真的很感激。或者如果那里有任何涵盖这个主题的教程?
非常感谢您的帮助。
答案 0 :(得分:5)
有一些不好的想法和好主意:
int
,long
,short
等类型,没有确切的大小保证。您可以使用int16_t
之类的内容,但这些内容仅适用于现代编译器。read
系统调用然后解析缓冲区 - 反之亦然,一次读取整个内容而不是更精细,懒惰的读取位置#39;适用)。有几种工具可以做到:
答案 1 :(得分:4)
读取结构定义的二进制文件很简单。
Format myFormat;
fread(&myFormat, sizeof(Format), 1, fp);
#defines根本不会影响结构。 (尽管如此,里面是一个奇怪的地方)。
但是,这不是跨平台安全的。在确保读者和作者使用相同平台的情况下,这是最简单的事情。
更好的方法是重新定义您的结构:
struct Format {
Uint32 str_totalstrings; //assuming unsigned long was 32 bits on the writer.
Uint32 str_name;
unsigned char stuff[4];
};
然后有一个'platform_types.h',它可以为你的编译器正确输入Uint32。现在你可以直接读到结构,但是对于endianness问题你仍然需要 做这样的事情:
myFormat.str_totalstrings = FileToNative32(myFormat.str_totalstrings);
myFormat.str_name = FileToNative32(str_name);
其中FileToNative是无操作或字节反转器,具体取决于平台。
答案 2 :(得分:2)
如果您有要在内存中解析的数据,也可以使用联合进行此解析。
union A {
char* buffer;
Format format;
};
A a;
a.buffer = stuff_you_want_to_parse;
// You can now access the members of the struct through the union.
if (a.format.str_name == "...")
// do stuff
还要记住,不同平台上的长度可能不同。如果您依赖于long一定大小,请考虑使用int stdint.h中定义的类型,例如uint32_t。
答案 3 :(得分:2)
使用C ++ I / O库:
#include <fstream>
using namespace std;
ifstream ifs("file.dat", ios::binary);
Format f;
ifs.get(&f, sizeof f);
使用C I / O库:
#include <cstdio>
using namespace std;
FILE *fin = fopen("file.dat", "rb");
Format f;
fread(&f, sizeof f, 1, fin);
答案 4 :(得分:0)
您必须找到写入文件的机器的endiannes,以便正确解释整数。注意ILP32与LP64的不匹配。原始结构包装/对齐可能也很重要。