0

I am new in here and I have a question I have a struct, let's say overall size is 8 bytes, here the struct:

struct Header 
{
    int ID;             // 4 bytes
    char Title [4];     // 4 bytes too
}; // so it 8 bytes right?

and I have a file with 8 bytes too... I just want to ask, how to parse data on that file into the struct of that

I have tried this one:

    Header* ParseHeader(char* filename)
    {
        char* buffer = new char[8];
        fstream fs(filename);

        if (fs.is_open() != true)
            throw new exception("Couldn't Open file for Parsing Header.");

        fs.read(buffer, 8);

        if (!fs)
        {
            delete[] buffer;
            throw new exception("Couldn't Read header OJN file.\nHeader data was corrupted");
        }

        Header* header = (Header*)((void*)buffer);
        delete[] buffer;
        fs.close();

        return header;
    }

but it fail, and return invalid data than what I was expect (I can make you sure, this is not file fault, the file structured correctly)

Can someone help me? Thanks

4 Answers 4

1

Seems like you do everything fine until this point:

Header* header = (Header*)((void*)buffer);
delete[] buffer;
fs.close();

notice you delete the buffer after the casting, meaning that header points to a deleted location -> junk, you need to either not delete or copy the data if you like to still use it.

Also, to be quite honest, I don't understand how your code compiles, your function states it returns a Header, while you return a Header*..

Sign up to request clarification or add additional context in comments.

Comments

0

You are deleting the data that is being returned. Therefore header is no longer accessible.

I think you meant the line to be:

Header header = *(Header*)((void*)buffer);

This will actually copy the header.

Comments

0

The fact that your 8 bytes file correctly maps to your struct Header is mere luck as far as C++ is involved. The structure could have internal padding that make it bigger than 8 bytes, and the data endianness could be different between your file and your CPU.

I realize your code works with your particular compiler version, on your operating system and on your CPU but you should not get into the habit of coding like that, otherwise you'll probably get into big trouble as soon as you change any of those parameters (or maybe even just some compiler flags). In other words, what you are doing is extremely bad practice. In C++ you don't even have the guarantee that an int is actually 4 bytes.

The Right Way™ to load such binary data from a file is to load each field individually and ensure proper endianness conversion depending on the CPU you're using (eg. through hton* / ntoh* or similar functions). Using a fixed-size type like int32_t also helps.

Comments

0

Just define your structure in 1-byte boundary as:

#pragma pack(1)
struct Header 
{
    int ID;             // 4 bytes
    char Title [4];     // 4 bytes too
};
#pragma pack()

First pack statement instructs the compiler to use one-byte padding for members in structure. This way size of Header will be 8 bytes. Second pack statement instructs to go back to default setting. You may need to use push and pop instructions (See enter link description here) - but this isn't required for you.

Secondly, and more importantly, you should not use hard-code values like 8. Always use sizeof to read or write a structure. Also, this statement is absolutely not needed:

char* buffer = new char[8];
...

Just declare Header variable itself, and read on it:

Header header;
...
fs.read(&header, sizeof(Header));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.