Say we have a struct of an int array, a float array etc. and we need to write them into a binary format file for fast reloading. Can this be done in a simple way?
Should the files be several for each of the array?
Say we have a struct of an int array, a float array etc. and we need to write them into a binary format file for fast reloading. Can this be done in a simple way?
Should the files be several for each of the array?
I'm a bit rusty in C, but it's likely someone has written support for serializing arrays into binary data specifically for writing to and/or reading from file. Google serialization for your specific language and it's likely someone has already solved this issue for you.
However, Endianness might be a problem, if you use some weird platform. Also you should probably use types that have fixed size on all platforms.
Unless you have a huge amount of data, just write a standard text format. If you can assume c99 on both ends, use the %a
formatter for floating-point data to insulate yourselves from the vagaries of binary-decimal conversion.
If the amount of data is huge, or you need to use a "raw data" format for other reasons, you will want to convert your data into a known endianness before writing, and convert back to the host endianness after reading. Any reasonably sane OS has library routines for doing these conversions.
If you are just looking for an example, the following is an extremely simple one with absolutely no error checking. It writes the contents of a structure with some integers in it to a file and then reads them back out again. The points made by others about byte order, though, are very germane and would need to be addressed if the file is to be used across different platforms.
typedef struct {
int count;
int *values;
} SomeInts;
int main(int argc, char* argv[])
{
SomeInts ints;
int i;
FILE *fh;
ints.count = 5;
ints.values = (int*)malloc( ints.count * sizeof(int));
for ( i = 0; i < ints.count; i++ )
ints.values[i] = i * 42;
// write it
fh = fopen( argv[1], "wb" );
// really should check amount written to verify it worked
fwrite( &ints.count, sizeof( ints.count ), 1, fh );
fwrite( ints.values, sizeof(ints.values[0]), ints.count, fh );
fclose(fh);
// read them back in.
free( ints.values );
memset( &ints, 0, sizeof( ints ));
fh = fopen( argv[1], "rb" );
// read how many ints (should also check for errors)
fread( &ints.count, sizeof( ints.count ), 1, fh );
ints.values = (int*)malloc( ints.count * sizeof(int));
fread( ints.values, sizeof(ints.values[0]), ints.count, fh );
fclose(fh);
for ( i = 0; i < ints.count; i++ )
printf( "%d\n", ints.values[i] );
free( ints.values );
}
If you use pragma pack(1), you can do the writes/reads in one hit on a chunk of memory.
#include <stdio.h>
#include <memory.h>
typedef struct ca_tag{
int i[4];
float f[3];
}ca_type;
#pragma pack(1)
void init(ca_type* c) // fill it with something
{
c->i[0] = 1; c->i[1] = 2; c->i[2] = 3; c->i[3] = 12;
c->f[0] = 2.3; c->f[1] = 32.3; c->f[2] = 42.3;
}
int main()
{
FILE *stream;
ca_type ca;
char *ptr = (char*)&ca;
char *ptr2 = (char*)&ca;
init(&ca);
if( (stream = fopen( "test.out", "wb" )) != NULL )
fwrite( ptr, sizeof( ca ), 1, stream );
else
printf( "Problem opening for write\n" );
fclose(stream);
memset((void *)&ca, 0, sizeof(ca));// zero the lot
if( (stream = fopen( "test.out", "rb" )) != NULL )
fread( (void*)ptr2, sizeof( ca ), 1, stream );
else
printf( "Problem opening for read\n" );
return 0;
}
Error checking needs doing as before