views:

73

answers:

6

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?

+1  A: 

Write in plain text ... and then zip it

Presto! binary format

pmg
Add some links to C APIs to get started (stdio, gzip, etc.), extra points for using standard library and cross platform libs.
Matt Joiner
A: 

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.

jpkomick
A: 

man fwrite/fread.

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.

Tuomas Pelkonen
+1  A: 

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.

Stephen Canon
A: 

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 );

}
Mark Wilkins
A: 

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

NickT