使用 C++/CLI 将二进制文件读入结构
Reading binary file into a struct using C++/CLI
我有一个问题(我认为它很容易解决,但它让我发疯)。我查看了其他帖子,但找不到解决方案。
我想使用 C++/CLI 将二进制文件读入结构。问题是在阅读之后,一些值与正确的值不符。在下面的示例中,所有结构字段都被很好地读取,直到 "a"(包括在内)(大约在字节 100 处)。从那个领域来看,其余的人都有错误的价值观。我知道它们有错误的值,而源文件是正确的,因为我之前使用了来自 C++/CLI 的 python、FileStream
和 BinaryReader
。但是,我不再使用它们了,因为我想将二进制文件读入结构。
此外,在某些情况下,变量 "size"(文件大小)的值也为 -1,但并非总是如此。我不确定当文件太大时它是否会得到错误的值。
因此,我的问题是你能看到我看不到的东西,或者我做错了什么。
struct LASheader
{
unsigned short x;
char y[16];
unsigned char v1;
unsigned char v2;
char y1[68];
unsigned short a;
unsigned long b;
unsigned long c;
unsigned char z;
unsigned short d;
unsigned long e;
}
void main()
{
FILE *ptr = fopen("E:\Pablo\file.las", "rb");
//I go at the end of the file to get the size
fseek(ptr, 0L, SEEK_END);
unsigned long long size = ftell(ptr);
struct LASheader lasHeader;
//I want an offset of 6 bytes
fseek(ptr, 6, SEEK_SET);
fread(&lasHeader, sizeof(lasHeader), 1, ptr);
unsigned short a1 = lasHeader.a;
unsigned long b1 = lasHeader.b;
unsigned long c1 = lasHeader.c;
unsigned short d1 = lasHeader.d;
unsigned long e1 = lasHeader.e;
}
谢谢!
巴勃罗.
这里有几件事。我将首先解决直接问题。
你没有说这个二进制格式是怎么写的,但我认为这是一个对齐问题。
没有 #pragma pack
指令,unsigned long b
将对齐到 4 字节边界。结构成员 x
到 a
总共有 90 个字节,因此在 a
和 b
之间插入了两个填充字节,以便 b
正确对齐。
要修复对齐方式,您可以用 #pragma pack(push, 1)
和 #pragma pack(pop)
.
包围结构
其次,一个更全面的问题:
您调用了此 C++/CLI 代码,并将其标记为 C++/CLI,但实际上您并未在此代码中使用任何托管功能。此外,您说您有一些使用 BinaryReader
工作的 C# 代码,并且 BinaryReader
在 C++/CLI 中工作正常,因此从技术上讲,您已经拥有了一个 C++/CLI 解决方案。
如果您的 C++/CLI 项目的其余部分是这种方式(不使用托管代码),请考虑将您的项目切换到 C++,或者拆分它。如果您的项目主要使用托管代码,那么我会强烈考虑使用 BinaryReader
而不是 fopen
来读取此数据。
我有一个问题(我认为它很容易解决,但它让我发疯)。我查看了其他帖子,但找不到解决方案。
我想使用 C++/CLI 将二进制文件读入结构。问题是在阅读之后,一些值与正确的值不符。在下面的示例中,所有结构字段都被很好地读取,直到 "a"(包括在内)(大约在字节 100 处)。从那个领域来看,其余的人都有错误的价值观。我知道它们有错误的值,而源文件是正确的,因为我之前使用了来自 C++/CLI 的 python、FileStream
和 BinaryReader
。但是,我不再使用它们了,因为我想将二进制文件读入结构。
此外,在某些情况下,变量 "size"(文件大小)的值也为 -1,但并非总是如此。我不确定当文件太大时它是否会得到错误的值。
因此,我的问题是你能看到我看不到的东西,或者我做错了什么。
struct LASheader
{
unsigned short x;
char y[16];
unsigned char v1;
unsigned char v2;
char y1[68];
unsigned short a;
unsigned long b;
unsigned long c;
unsigned char z;
unsigned short d;
unsigned long e;
}
void main()
{
FILE *ptr = fopen("E:\Pablo\file.las", "rb");
//I go at the end of the file to get the size
fseek(ptr, 0L, SEEK_END);
unsigned long long size = ftell(ptr);
struct LASheader lasHeader;
//I want an offset of 6 bytes
fseek(ptr, 6, SEEK_SET);
fread(&lasHeader, sizeof(lasHeader), 1, ptr);
unsigned short a1 = lasHeader.a;
unsigned long b1 = lasHeader.b;
unsigned long c1 = lasHeader.c;
unsigned short d1 = lasHeader.d;
unsigned long e1 = lasHeader.e;
}
谢谢!
巴勃罗.
这里有几件事。我将首先解决直接问题。
你没有说这个二进制格式是怎么写的,但我认为这是一个对齐问题。
没有 #pragma pack
指令,unsigned long b
将对齐到 4 字节边界。结构成员 x
到 a
总共有 90 个字节,因此在 a
和 b
之间插入了两个填充字节,以便 b
正确对齐。
要修复对齐方式,您可以用 #pragma pack(push, 1)
和 #pragma pack(pop)
.
其次,一个更全面的问题:
您调用了此 C++/CLI 代码,并将其标记为 C++/CLI,但实际上您并未在此代码中使用任何托管功能。此外,您说您有一些使用 BinaryReader
工作的 C# 代码,并且 BinaryReader
在 C++/CLI 中工作正常,因此从技术上讲,您已经拥有了一个 C++/CLI 解决方案。
如果您的 C++/CLI 项目的其余部分是这种方式(不使用托管代码),请考虑将您的项目切换到 C++,或者拆分它。如果您的项目主要使用托管代码,那么我会强烈考虑使用 BinaryReader
而不是 fopen
来读取此数据。