Reputation: 62
I'm having trouble reading from a binary file into a struct given a specific format. As in, given a byte-by-byte definition (Offset: 0 Length: 2 Value: 0xFF 0xD8, Offset: 2 Length: 2 Value: 0xFF 0xE1, etc), I'm not sure how to define my structure nor utilize file operations like fread(); to correctly take in the information I'm looking for.
Currently, my struct(s) are as follows:
struct header{
char start; //0xFF 0xD8 required.
char app1_marker; //0xFF 0xE1 required. Make sure app0 marker (0xFF 0xE0) isn't before.
char size_of_app1_block; //big endian
char exif_string; //"EXIF" required
char NULL_bytes; //0x00 0x00 required
char endianness; //II or MM (if not II break file)
char version_number; //42 constant
char offset; //4 blank bytes
};
and
struct tag{
char tag_identifier;
char data_type;
char size_of_data;
char data;
};
What data types should I be using if each attribute of the structure has a different (odd) byte length? Some require 2 bytes of space, others 4, and even others are variable/dynamic length. I was thinking of using char arrays, since a char is always one byte in C. Is this a good idea?
Also, what would be the proper way to use fread if I'm trying to read the whole structure in at once? Would I leave it at:
fread(&struct_type, sizeof(char), num_of_bytes, FILE*);
Any guidance to help me move past this wall would be greatly appreciate. I already understand basic structural declerations and constructions, the two key issues I'm having is the variance and odd byte sizes for the information and the proper way to read variable byte sizes into the struct in one fread statement.
Here is the project link: http://people.cs.pitt.edu/~jmisurda/teaching/cs449/2141/cs0449-2141-project1.htm
Upvotes: 0
Views: 4536
Reputation: 70402
I usually see fread()
on structures specify the size as the structure size, and the number of elements as 1
, and the expectation that fread()
returns 1:
size_t result = fread(&record, num_of_bytes, 1, infile);
I am uncertain how you figure out if your endianess
field is II
or MM
, but I guess the idea is that you could decide whether or not to fix up the field values based on whether the file endianess matches the host endianess.
The actual data seems to be the tag
structures, and the last field data
is actually just a place holder for variable length data that is specified in the size_of_data
field. So I guess you would first read sizeof(struct tag) - 1
bytes, and then read size_of_data
more bytes.
struct tag taghdr;
size_t result = fread(&taghdr, sizeof(taghdr) - 1, 1, infile);
if (result != 1) { /* ...handle error */ }
struct tag *tagdata = malloc(sizeof(taghdr) + taghdr.size_of_data - 1);
if (tagdata == 0) { /*...no more memory */ }
memcpy(tagdata, &taghdr, sizeof(taghdr) - 1);
if (taghdr.size_of_data > 0) {
result = fread(&tagdata->data, taghdr.size_of_data, 1, infile);
if (result != 1) { /*...handle error */ }
}
Upvotes: 2