C for Yourself - part 35

Steve Mumford reads and writes data to the file

The actual process of saving a file is relatively straightforward — in this case I've simply opened a file with write access, then cycled through all the structures within the linked list, printing out their values to the open file.

Once the last record in the chain is reached, the file is closed, and at that stage can be filetyped according to the value originally submitted with the DataSave message. We've used the fopen() function before; we call it with two parameters — a filename and an access mode — and the value that it returns can be used as a handle to access that file.

To actually save the data to the file, I've used the fprintf() function — as its name suggests, it's very similar to printf() in layout and the only extra parameter it requires is a file pointer to determine the destination of the output it produces. The output can be formatted in exactly the same way as if you were printing to the screen. The general structure of the proce- dure is shown below.

FILE *file_ptr;
char filename[] = "testfile";
file_ptr = fopen(filename, "wb");
do
{
  fprintf(file_ptr, "%d\n", currentrecord->jump_no);
  /* Write data for each record here */
} while (FILE_END != TRUE);
fclose(file_ptr);

However, as discussed before, it's a good idea to include extra flags here and there to indicate such things as the program version number, the end of each record and the end of the file — the more work you do now to lay your data out in a rigid format, the easier it'll be to load the file again.

Loading files tends to involve a little more work — in this case, that's because the memory for the data structures has to be allocated as we go along, and we don't immediately know how many records we're going to read. Because I've used a textual format for the representation of our data, I also need to translate a couple of the strings into integers so that they match with the variable type that holds them in memory.

Be careful when reading in text from a file — some of the input functions in C terminate their input at any 'whitespace' character. So if one of the data fields contains more than one word and you were to load it using one of the above functions, everything after the first space would be lost. There would also be a chance of the 'lost' input clogging up the buffer and throwing the loading sequence out of step.

I've used the fgets() function to read each line of the saved file. This will terminate at a newline character and will treat a 'space' as a normal character — exactly what we want. It's wise to use a bit of 'scratch space' so that you can load a line of the file into a buffer, translate it if necessary and from there store it to its final home in memory.

char buffer[256];
FILE *file_ptr;
char filename[] = "testfile";
file_ptr = fopen(filename, "rb");

do
{
  /* setup storage space */
  fgets(buffer, 255, file_ptr);
  /* translate line and store it */
}

Several 'conversion' functions are available within C; I've been using atoi() to translate a string of characters into an integer — both the altitude of each parachute jump and the delay are stored in this format.

temp_ptr->altitude = atoi(buffer);

All that remains is to intercept the WIMP's message telling us that the user is trying to drop a file on us — it's got a message number of 3 and the full pathname of the file is stored 44 bytes from the start of the poliblock. It also contains data on the type of the file and its estimated size, as well as which window or icon the file was dropped on to.

All this information should be checked carefully — you don't want to go about loading any old file that comes your way, and you might want to respond to files dropped in a window in a different fashion to those deposited on the icon bar — merging instead of loading anew.

Finally, once you've loaded the data successfully, reply to the original message with Message_DataLoadAck so that the WIMP knows the operation has been a success.


Source: Acorn User - 179 - March 1997
Publication: Acorn User
Contributor: Steve Mumford