Read Binary File into a Struct

Reading binary data into struct with ifstream

As the comment above states, you are probably missing hdr.length and hdr.count.
I tried it with gcc 4.8 and clang 3.5 and it works correctly.

#include <iostream>
#include <fstream>

#pragma pack(push, r1, 1)
struct Header {
char id[15];
int length;
int count;
};
#pragma pack(pop, r1)

int main() {
Header h = {"alalalala", 5, 10};

std::fstream fh;
fh.open("test.txt", std::fstream::out | std::fstream::binary);
fh.write((char*)&h, sizeof(Header));
fh.close();

fh.open("test.txt", std::fstream::in | std::fstream::binary);

fh.read((char*)&h.id, sizeof(h.id));
fh.read((char*)&h.length, sizeof(h.length));
fh.read((char*)&h.count, sizeof(h.count));

fh.close();

std::cout << h.id << " " << h.length << " " << h.count << std::endl;
}

How to read a binary file to a structure in C

You have to pass pointers to have fread() read data.

void reading(FILE *fp){

Product *obuff = malloc(sizeof(Product));
fread(&obuff->code, sizeof(obuff->code), 1, fp);
fread(&obuff->name, sizeof(obuff->name), 1, fp);
fread(&obuff->quantity, sizeof(obuff->quantity), 1, fp);
fread(&obuff->price, sizeof(obuff->price), 1, fp);

printf("%s %s %d %.2f\n", obuff->code, obuff->name, obuff->quantity, obuff->price);
free(obuff); /* free whatever you allocated after finished using them */
}

Reading a binary file into a struct

Use the struct module; you need to define the types in a string format documented with that library:

struct.unpack('=HHf255s', bytes)

The above example expects native byte-order, two unsigned shorts, a float and a string of 255 characters.

To loop over an already fully read bytes string, I'd use itertools; there is a handy grouper recipe that I've adapted here:

from itertools import izip_longest, imap
from struct import unpack, calcsize

fmt_s = '=5i'
fmt_spec = '=256i'
size_s = calcsize(fmt_s)
size = size_s + calcsize(fmt_spec)

def chunked(iterable, n, fillvalue=''):
args = [iter(iterable)] * n
return imap(''.join, izip_longest(*args, fillvalue=fillvalue))

data = [unpack(fmt_s, section[:size_s]) + (unpack(fmt_spec, section[size_s:]),)
for section in chunked(bytes, size)]

This produces tuples rather than lists, but it's easy enough to adjust if you have to:

data = [list(unpack(fmt_s, section[:size_s])) + [list(unpack(fmt_spec, section[size_s:]))]
for section in chunked(bytes, size)]

Reading binary file and storing it to struct in c

After three hours of research, I finally concluded that the problem was it's missing a NUL terminator. Using printf with a non-null terminated string

This solved my problem:

...
printf("ChunkID: %.*s\n",4,WAV_HEADER.ChunkID);
printf("ChunkSize: %u\n",WAV_HEADER.ChunkSize);
printf("Format: %.*s\n",4,WAV_HEADER.Format);
...

how to read from binary file into struct c?

If I understand correctly, you're asking if you can do

struct record r;
fread(file, &r, sizeof(r));

or are you forced to use

struct record r;
fread(file, &r.order, sizeof(r.order));

If this is your question, then the answer is: you have to read the fields one-by-one since there may be padding between struct members. Or, if you use a GNU-compatible compiler, you might instruct it not to include any padding by declaring your struct as "packed":

struct record {
// ...
} __attribute__((packed));

But this is not advised unless absolutely necessary (it's not portable).

Also, is your file really a binary file? If not, you should pay attention to newline characters and converting the numbers from text to their actual numeric value.

Read binary file into struct (translating instructions)

Ok, this is not a full answer but I feel comments would be really unreadable here.

The first step is reading the first 12 bytes (three 4-bytes integers), and unpack them so we can check the endianness. Let's try big-endian first

from struct import *
with open(file, "rb") as f:
byte = f.read(12)
header_size, int32key, file_endian = unpack('>3i', byte)

We expect to have int32key set at 305419896 (= \x12345678). If we get another value then let's switch to little-endian, i.e. change our unpack format string to <3i.

At this point we can read the rest of the header, with the same logic, and get all the info we need to read data for the first channel. I hope this can be a good start for you.

Reading Binary File into a Structure (C++)

Your struct has almost certainly been padded to preserve the alignment of its content. This means that it will not be 37 bytes, and that mismatch causes the reading to go out of sync. Looking at the way each string is losing 3 characters, it seems that it has been padded to 40 bytes.

As the padding is likely to be between the string and the integers, not even the first record reads correctly.

In this case I would recommend not attempting to read your data as a binary blob, and stick to reading individual fields. It's far more robust, especially if you even want to alter your structure.

Read binary data (from file) into a struct

C structs are just about grouping related pieces of data together, they do not specify a particular layout in memory. (Just as the width of an int isn't defined either.) Little-endian/Big-endian is also not defined, and depends on the processor.

Different compilers, the same compiler on different architectures or operating systems, etc., will all layout structs differently.

As the file format you want to read is defined in terms of which bytes go where, a struct, although it looks very convenient and tempting, isn't the right solution. You need to treat the file as a char[] and pull out the bytes you need and shift them in order to make numbers composed of multiple bytes, etc.

Read binary file into struct and also problems with endianness

  • You must allocate the structure and read data into the structure instead of reading into an pointer directly. If you are going to read only one structure, you won't need to declare pointers for the structure.
  • printf("%x ", test->magic); invokes undefined behavior because pointer (automatically converted from the array) is passed to where unsigned int is required.

In this case, the observed behavior is because:

Firstly, fread(&test,sizeof(test),1,fp); read the first few bytes from the file as pointer value.

Then, printf("%02x", test->magic); printed the first 4-byte integer from the file because test->magic is (converted to) the pointer to the array placed at the top of the structure, and the address of the array is same as the address of the structure itself, so the address read from the file is printed. One more lucky is that where to read 4-byte integer and address (pointer) from as function arguments are the same.

Finally, you didn't get any output from printf("%x ", test->version); because the address read from the file is unfortunately in region that is not readable and trying to read there caused Segmentation Fault.

Fixed code:

using namespace std;

#include <stdint.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include "exampleh.h"

struct teststruct test; // allocate structure directly instead of pointer

int main() {
FILE *fp = fopen("C:\\image.dd", "rb"); // open file in binary mode

if (fp == NULL) {
fprintf(stderr, "Can't read file");
return 0;
}
fread(&test,sizeof(test),1,fp); // now structure is read instead of pointer
for (int i = 0; i < 6; i++) {
printf("%02x", (unsigned char)test.magic[i]); // print using proper combination of format and data
}
printf(" ");
printf("%x ", test.version); // also use . instead of ->

fclose(fp);

return 0;
}


Related Topics



Leave a reply



Submit