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: 6904
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 15: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 15 2004 at 01: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 09: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 10: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 08: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 20: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, 20:41:40

Posted By: rkzad on Apr 03 2004 at 18: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 20: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 23: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, 23:44:12

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

Posted By: Persuter on Apr 12 2004 at 21: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, 21:20:03

Posted By: hanfling on Apr 14 2004 at 11: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 10: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 10: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 05 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
knock knock
General | News
By: omega | Dec 22 2016
 
knock knock
General | News
By: MIFUNE | Oct 10 2015
 
New HL HUD Message System
Half-Life | Coding | Shared Tutorials
By: chbrules | Dec 31 2011
 
knock knock
General | News
By: Whistler | Nov 05 2011
 
Particle Engine tutorial part 4
Half-Life | Coding | Client Side Tutorials
By: darkPhoenix | Feb 18 2010
 
Particle Engine tutorial part 2
Half-Life | Coding | Client Side Tutorials
By: darkPhoenix | Feb 11 2010
 
Particle Engine tutorial part 3
Half-Life | Coding | Client Side Tutorials
By: darkPhoenix | Feb 11 2010
 
Game Movement Series #2: Analog Jumping and Floating
Half-Life 2 | Coding | Shared Tutorials
By: mars3554 | Oct 26 2009
 
Particle Engine tutorial part 5
Half-Life | Coding | Client Side Tutorials
By: Deadpool | Aug 02 2009
 
Particle Engine tutorial part 5
Half-Life | Coding | Client Side Tutorials
By: Persuter | Aug 02 2009
 

Site Info
297 Approved Articless
8 Pending Articles
3940 Registered Members
0 People Online (7 guests)
About - Credits - Contact Us

Wavelength version: 3.0.0.9
Valid XHTML 1.0! Valid CSS!