Search code examples
c++-clibinaryfiles

Reading binary file into a struct using C++/CLI


I have a problem (and I think it can be resolved easily, but it is driving me crazy). I have checked other posts, but I was not able to find the solution.

I would like to read a binary file into a struct using C++/CLI. The problem is that after reading it, some of the values do not fit with the correct ones. In the example below, all the struct fields are well read until "a" (included) (at around byte 100). From that field, the rest have wrong values. I know that they have wrong values and the source file is right, since I previously used python, and FileStream and BinaryReader from C++/CLI. However, I am not using them anymore, given that I would like to read the binary file into a struct.

In addition, in some cases I also have a value of -1 for variable "size" (size of the file), but not always. I am not sure if it could get a wrong value when the file is too big.

Therefore, my question if you can see something that I cannot, or I am doing something wrong.

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

Thank you!

Pablo.


Solution

  • There's a couple things here. I'll tackle the direct problem first.


    You didn't say how this binary format was being written, but I think it's an alignment issue.

    Without a #pragma pack directive, unsigned long b will align to a 4-byte boundary. Struct members x through a are 90 bytes total, so two padding bytes are inserted between a and b so that b is aligned properly.

    To fix the alignment, you can surround the struct with #pragma pack(push, 1) and #pragma pack(pop).


    Second, a more overall issue:

    You called this C++/CLI code, and you tagged it C++/CLI, but you're not actually using any managed features in this code. Also, you said you have some C# code that works using BinaryReader, and BinaryReader works fine in C++/CLI, so you technically already had a C++/CLI solution in-hand.

    If the rest of your C++/CLI project is this way (not using managed code), consider switching your project to C++, or perhaps splitting it. If your project is largely making use of managed code, then I would strongly consider using BinaryReader instead of fopen to read this data.