简体   繁体   中英

Converts Bits to Human readable format

I want to read a binary file into a struct

struct rec
{
    int type;
    long length;
    int data[100];
};

The first 16 bits of the binary file is the type, the next 32 bits is the length of the data, the next is the data. There are multiple records in the file and the last record has the length 0 representing the end of file.

I want to read and print the values of each record.

I figured out a way to read type and length, but I'm stuck while trying the use the length the read the data. Also, how can I put this in a loop until length = 0?

int main()
{
    FILE *ptr_tofile;
    struct rec some_record;
    ptr_tofile=fopen("Test.bin","rb");

    if (!ptr_tofile)
    {
        printf("Unable to open file!");
        return 1;
    }

    for ( until length = 0)
    {
        fread(&some_record, sizeof(int), 1, ptr_tofile);
        printf("%d\n",some_record.type);
        fread(&some_record, sizeof(int), 2, ptr_tofile);
        printf("%d\n",some_record.type);
        getch();
    }
    fclose(ptr_tofile);
    return 0;
}

Here is an alternative method to using a flexible array member:

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

typedef struct file_s {
  int16_t type;
  int32_t length;
  // Assumption: Each record is 16 bits
  // For a record size of 32 bits, use int32_t*
  int16_t* data;
} file_s;

int main() {
  file_s file;
  FILE* f = fopen("file.bin","r");
  if (f == NULL) {
    perror("Error");
    return 1;
  }
  fread(&file.type, sizeof(file.type), 1, f);
  fread(&file.length, sizeof(file.length), 1, f);
  // Assumption: the length of the data is the number of records
  // If the length is in bytes, you should divide it by the size
  // of a record to obtain the number of records
  file.data = malloc(file.length * sizeof(*file.data));
  // sizeof is a compile-time operator so sizeof(*p) is not a null dereference
  fread(file.data, sizeof(*file.data), file.length, f);
  fclose(f);
  // Process the data
  /* ... */
  free(file.data);
  return 0;
}

There are some assumptions made on what the length is representing and the size of a record, but you can adapt this to fit the specifics of your problem.

You can define a flexible array in struct like:

#pragma pack(push, 1)
typedef struct {
    int16_t type;
    int32_t length;
    int     data[];
} record_t;
#pragma pack(pop)

and use the following pseudo code to read one record.

record_t *r1;
r1 = calloc(1, sizeof(record_t));
//read the record head to r1, sizeof(record_t)
r1 = realloc(r1, r1->length*sizeof(int)+sizeof(record_t));
//read the rest of the record to r1->data, assume it is of type int.

Note the #pragma pack is important, as it can avoid compiler align data in the struct, so it can match exactly your on disk format!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM