Welcome, Guest! Login | Register

Reading and Writing Entire Structures [Print this Article]
Posted by: Mazor
Date posted: Jan 14 2004
User Rating: 5 out of 5.0
Number of views: 4631
Number of comments: 14
Description: This shows how easy it is to read and write entire structs to and from a file. With this information, it is easy to develop your own file formats!
Reading and Writing Structures to/from Files
by: Cale "Mazor" Dunlap
---------------------------------------------------

This tutorial is simple, and very straightforward. Most programmers know by now that it is possible to read and write entire data structures to files binarily (sp?). I did not know this until a few weeks ago, and I've been doing this stuff for years (shows where I've been, hehe). All this tutorial really needs is fopen, fread, fwrite, and fclose. So... here goes nothing:

First, include the right files:
 CODE (C++) 

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


Then, create your struct (file format):
 CODE (C++) 

struct DATA
{
     unsigned char data1[1024]; // big values are cool! :P
     bool data2;
     unsigned short data3;
     unsigned long data4;
};

Now we start the main driver, which handles everything:
 CODE (C++) 

int main( int argc, char *argv[] )
{
     // create some data
     DATA *pData = new DATA;
     // since data1's array size is 1024, try and put as much data into it as you can
     strcpy(pData->data1, "Hello from data1 of the DATA struct!!!!");
     pData->data2 = true;
     pData->data3 = 293742346876345; // jibberish number
     pData->data4 = 5994572987429687657589579847967495; // jibberish number

     // write the data structure to a file
     FILE *pFile = fopen("data.txt", "wb"); // notice the "wb" for write in binary mode?
     fwrite(pData, sizeof(struct DATA), 1, pFile); // third param is always 1 (at least everything that I've seen)
     fclose(pFile); // close the file

     delete pData; // delete the structure (we don't want leaks)

     // read the file BACK into memory
     DATA *pRead = new DATA; // create another instance of the structure for reading
     pFile = fopen("data.txt", "rb"); // note the "rb" for read binary mode
     fread(pRead, sizeof(struct DATA), 1, pFile); // this is almost exactly the same as the fwrite call
     fclose(pFile); // close the file again

     // output the struct data
     printf("%s\n%i\n%i\n%i\n", pRead->data1, pRead->data2, pRead->data3, pRead->data4);

     delete pRead; // again, no memory leaks

     return 0; // any function (declared as int) returns a value
}


This will output the same data we put INTO the struct in the main driver, to the data that was read OUT of the struct into the console.
NOTE: Open the file in notepad once, notice how it looks nothing like plain text? :)

Any Q's, email meh!
mazor@firearmsmod.com

-Cale

Rate This Article
This article is currently rated: 5 out of 5.0 (2 Votes)

You have to register to rate this article.
User Comments Showing comments 1-14

Posted By: Persuter on Jan 14 2004 at 09:03:51
If pData was an array of size N, i.e., DATA* pData = new DATA[N];, then you would use fwrite( pData, sizeof( struct DATA ), N, pFile ); That's why it's 1.

Posted By: rkzad on Jan 14 2004 at 19:51:34
I don't think you really needed to use pointers for this example, for clarity at least.

You could simply say DATA data;, and instea of sending pData, send &data.

I guess you used your method to ensure you were reading data from the file, so this comment is more to give another example how to use it, heh.

PS It's not called a driver :p it's a function. If you want to say something other than main function you could say entry-point function.

Posted By: Mazor on Jan 17 2004 at 03:49:56
I had never seen WHY it was 1, but I guess that makes sense if you're writing entire arrays of structures. Thanx for the info!

Posted By: Mazor on Mar 14 2004 at 04:31:25
rkzad:

My programming teachers always called it a main driver. I thought it was stupid too--and now I catch myself using it. I never called it a main driver until I got into an official C programming course, and these are the people shaping the minds of future programmers. Oh god!

BTW: Most of these teachers were RPG or COBOL programmers back in the day, that might have something to do with it.

Posted By: Persuter on Mar 26 2004 at 02:15:24
Didn't notice you wrote this until a bit ago, Mazor. Don't worry too much, the guys I work with often call functions "drivers" as well. Generally they're referring to a function that runs a simulation using a mathematical library.

Posted By: jim_the_coder on Apr 02 2004 at 14:39:47
"This shows how easy it is to read and write entire structs to and from a file. With this information, it is easy to develop your own file formats!"

Can you explain to me very roughly how I could develop my own file format? I see how you're writing and reading the data in binary, but not how I'd create my own format.Edited by jim_the_coder on Apr 02 2004, 14:41:40

Posted By: rkzad on Apr 03 2004 at 12:05:36
As for format, it's up to you. There's no specific way to make a file format. You just write it how you want, and read it how you want. If it's different from anything else out there, you can call it your own file format.

As for the "drivers" bit, don't get in the habit :p Gets confusing with actual drivers, heh. If you're in the habit, break free!

Posted By: jim_the_coder on Apr 03 2004 at 14:48:17
Cheers rkzad :) so if I came up with some system for storing data in varying arrays depending on character, that would count as a format??

Posted By: DarkAngelZLT on Apr 05 2004 at 18:42:39
a "format" is just a way of storing data. If youve created a file with data in it, that data must be in some kind of format otherwise its just meaningless garbage isnt it?
A simple format might read a header structure which tells info, such as perhaps how many other structures are saved in the file, or what kind of data is in it. Then you can loop thru with this code reading the other structures.Edited by DarkAngelZLT on Apr 05 2004, 18:44:12

Posted By: jim_the_coder on Apr 06 2004 at 13:51:32
Thanks for clearing that up DarkAngel :) mwahaha time to create me a .jim format...

Posted By: Persuter on Apr 12 2004 at 16:17:45
Let's take a simple example. Say I want to store a polygon mesh in a binary file. I need to have the number of vertices and the number of polygons, and then I need to store the actual vertex positions and polygon vertex indices.

 CODE (C++) 
int numVertices, numPolygons;

// Fill in numbers here

float* VertexPositions = new float[numVertices*3];
int* PolygonIndices = new int[numPolygons*3];

// Fill in arrays here

// Now we write them out to some file
FILE* fp = fopen( myfile, "wb" );
fwrite( &numVertices, sizeof( int ), 1, fp );
fwrite( &numPolygons, sizeof( int ), 1, fp );
fwrite( VertexPositions, sizeof( float ), numVertices*3, fp );
fwrite( PolygonIndices, sizeof( int ), numPolygons*3, fp );
fclose( fp );


Conversely, to read them in:

 CODE (C++) 

int numVertices, numPolygons;
float* VertexPositions;
int* PolygonIndices;

FILE* fp = fopen( myfile, "rb" );
fread( &numVertices, sizeof( int ), 1, fp );
fread( &numPolygons, sizeof( int ), 1, fp );

VertexPositions = new float[numVertices*3];
PolygonIndices = new int[numPolygons*3];

fread( VertexPositions, sizeof( float ), numVertices*3, fp );
fread( PolygonIndices, sizeof( int ), numPolygons*3, fp );
fclose( fp );


And, voila! This is the quickest and easiest way to output binary data to a file. This is technically a "file format", although it's very simple. All it means is that I've got some data in a specified order and format. Basically fread and fwrite are used to "save" C variables to files.

(P.S. Note that I used "rb" and "wb" when opening the files. That opens them in binary mode. Note that in fact this is the default behavior, but it is important for ISO C conformance. Which is not that important, but still, one extra letter.)Edited by Persuter on Apr 12 2004, 16:20:03

Posted By: hanfling on Apr 14 2004 at 06:33:43
I would not recommend to write whole structures to disk. It's the best way to make your binaray files plattform and compiler depend.
Why?
For Example take following struct:
struct foo {
int bar;
char foo;
bool b;
}
You would expect the size of the struct as sizeof(int) + sizeof(char) + sizeof(bool), but it's normally huger. Why?
The variables are align to 4bit, 8bit steps whatever, so if we would have a 16bit int, char = 1byte, bool = 1byte and an 4bit allignment the struct in memory whould look something like this.
byte 0-1: variable bar
byte 2-3: padding
byte 4: variable foo
byte 5-7: padding
byte 8: variable b

So the struct in memory has some filling stuff in it. When you write the whole struct directly to disk, you also would write this to hard disk. On another compiler, these Paddings can differ.
There are some compiler specific keywords/preprocessor defines to avoid these problems.
But to write a really portable programm, you should write each variable on its own to disk.

Posted By: chbrules on Nov 28 2004 at 04:41:04
A bit on what hanfling said, if you're confused why this is an issue, it's because the physical space the variables take it, they differ from platform to platform. An int variable for example, on a Windows 32-bit system, the int variable is 4bytes long, on some older systems such as DOS, it's actually 2bytes long. So this would mean that if you wrote this struct to disc on a W32 system and tried to read it on a DOS 16-bit system you'd get bad values for your variables as it would look for the first 2 bytes and not all 4, or vice versa. Here's a page with some references to the byte size of variables if anyone cares: http://www.cplusplus.com/doc/tutorial/tut1-2.html (The data types table)

Posted By: monokrome on Jan 27 2007 at 04:14:38
lol... For some reason, I've never realized the fact that that's all there is to writing binary to a file. I think that's one of those neato things that nobody really ever realizes. Crazy.

Thanks for the article!


You must register to post a comment. If you have already registered, you must login.

Latest Articles
3rd person View in Multiplayer
Half-Life 2 | Coding | Client Side Tutorials
How to enable it in HL2DM

By: cct | Nov 13 2006

Making a Camera
Half-Life 2 | Level Design
This camera is good for when you join a map, it gives you a view of the map before you join a team

By: slackiller | Mar 04 2006

Making a camera , Part 2
Half-Life 2 | Level Design
these cameras are working monitors that turn on when a button is pushed.

By: slackiller | Mar 04 2006

Storing weapons on ladder
Half-Life 2 | Coding | Snippets
like Raven Sheild or BF2

By: British_Bomber | Dec 24 2005

Implementation of a string lookup table
Half-Life 2 | Coding | Snippets
A string lookup table is a set of functions that is used to convert strings to pre-defined values

By: deathz0rz | Nov 13 2005


Latest Comments
Spinning Corpses Simple Fix
Half-Life | Coding | Snippets
By: darkPhoenix | Sep 05 2008
 
Where do we go from here
General | News
By: MIFUNE | Jun 09 2008
 
The Input/Output system
Half-Life 2 | Level Design
By: nazitaco | Dec 23 2007
 
Where do we go from here
General | News
By: Rob_F | Nov 22 2007
 
Rescaling Half-Life
Half-Life | Coding | Shared Tutorials
By: christoph | Nov 12 2007
 
GameUI
Half-Life 2 | Coding | Client Side Tutorials
By: Evil_j | Oct 29 2007
 
3 State Zoom For Any Weapon
Half-Life 2 | Coding | Server Side Tutorials
By: Ennuified | Oct 18 2007
 
Storing weapons on ladder
Half-Life 2 | Coding | Snippets
By: cct | Sep 07 2007
 
CTF Gameplay Part 1
Half-Life | Coding | Shared Tutorials
By: DarkNight | Aug 28 2007
 
CTF Gameplay Part 1
Half-Life | Coding | Shared Tutorials
By: deedok | Aug 20 2007
 

Site Info
296 Approved Articless
5 Pending Articles
3940 Registered Members
0 People Online (14 guests)
About - Credits - Contact Us

Wavelength version: 3.0.0.9
Valid XHTML 1.0! Valid CSS!