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:
| | | #include <stdio.h> #include <stdlib.h> #include <string.h>
|
Then, create your struct (file format):
| | | struct DATA { unsigned char data1[1024]; bool data2; unsigned short data3; unsigned long data4; };
|
Now we start the main driver, which handles everything:
| | | int main( int argc, char *argv[] ) { DATA *pData = new DATA; strcpy(pData->data1, "Hello from data1 of the DATA struct!!!!"); pData->data2 = true; pData->data3 = 293742346876345; pData->data4 = 5994572987429687657589579847967495;
FILE *pFile = fopen("data.txt", "wb"); fwrite(pData, sizeof(struct DATA), 1, pFile); fclose(pFile);
delete pData;
DATA *pRead = new DATA; pFile = fopen("data.txt", "rb"); fread(pRead, sizeof(struct DATA), 1, pFile); fclose(pFile);
printf("%s\n%i\n%i\n%i\n", pRead->data1, pRead->data2, pRead->data3, pRead->data4);
delete pRead;
return 0; }
|
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 |
|
User Comments
Showing comments 1-14
|
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. |
|
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. |
|
|
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! |
|
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. |
|
|
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. |
|
"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
|
|
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! |
|
|
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?? |
|
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
|
|
|
Thanks for clearing that up DarkAngel :) mwahaha time to create me a .jim format... |
|
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.
| | | int numVertices, numPolygons;
float* VertexPositions = new float[numVertices*3]; int* PolygonIndices = new int[numPolygons*3];
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:
| | | 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
|
|
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. |
|
|
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) |
|
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.
|
296 Approved Articless
5 Pending Articles
3940 Registered Members
0 People Online (14 guests)
|
|