C Tutorial (28) : Disk Files (Sequential Access)

one of the programs you’ve seen so far has been able to store data for very long. If you defined an integer variable, put a 14 in it, and then turned off the computer that variable would no longer have 14 in it. If you turned your computer back on and tried to find the value in the variable, you couldn’t find it—no way.

This tutorial explains how to save data to your disk. When the data is on your disk, it will be there until you change or erase it. Data on your disk is just like music on a tape. You can turn off the tape deck, and the tape will hold the music until you change it.

Disk Files

Disks hold data in files. Files can hold either programs or data. Your programs must be loaded from disk into memory before you can run them. You also must load data from the disk file into variables before you can work with the data. The variables also hold data before the data goes to a disk file.

Two types of files exist: sequential-access files and random-access files. Their types determine how you can access them. If you work with a sequential-access file, you have to read or write the file in the order of the data. In a random-access file, you can jump around, reading and writing any place in the file.

Tip : A sequential file is like a video tape, and a random-access file is like a DVD or Blu-Ray. You have to watch a movie in sequence on a tape (or fast-forward through it in order), whereas you can skip to different chapters on a DVD or a Blu-Ray.

All disk files have names that conform to the same naming rules as filenames on your operating system. Before you can use a disk file, whether to create, read, or change the data in the file, you must open the file.

You can’t use a disk file without opening the file. Instead of pulling out a drawer, your computer attaches something called a file pointer to the file and makes sure that the disk is properly set up to hold the file you specify.

Opening a File

To open a file, you must use the fopen() function, whose description is included stdio.h. Before seeing fopen(), you have to understand the concept of a file pointer.

A regular pointer holds the address of data in a variable. A file pointer holds the disk location of the disk file you’re working with.

As with any variable, you can name file pointers anything you want.

FILE * fptr;       /* Defines a file pointer named fptr */

Note : This makes the file pointer global, which is a fancy term meaning that the entire program can use the file. (Most other kinds of variables are local, not global.) FILE is defined in stdio.h.

After you define a file pointer, you can connect that pointer to a file with fopen(). After you specify fopen(), you can use the file throughout the rest of the program.

#include <stdio.h>

main()
{
FILE *fptr; // Defines a file pointer
fptr = fopen("c:\cprograms\cdata.txt", "w"); 
// rest of program would follow

fclose (fptr); // Always close files you've opened

For the rest of the program, you’ll access the cdata.txt file via the file pointer, not via the filename.

Warning : Close all open files when you’re finished with them, or you could lose some data. fclose() is the opposite of fopen(). In its parentheses, fclose() requires a file pointer of the file you want to close.

If the file pointer equals 0, you know that an error happened. For example, if you attempt to open a file on a disk drive that doesn’t exist, fopen() returns an error.

The “w” (the second argument in the previous code’s fopen()) means write.

c_file_access_mode

The Basic fopen() Mode Strings

Using Sequential Files

You’ll do only three things with a sequential file: create it, read it, and add to it (write to it). To write to a file, you can use fprintf(). fprintf() is easy because it’s just a printf() with a file pointer at the beginning of its parentheses. The following program creates a file and writes some data to it using fprintf():

/* The program takes the book info and 
   writes the info to a file named bookinfo.txt. */

//First include the file with the structure definition 
#include "bookinfo.h"
#include <stdio.h> 
#include <stdlib.h> 

FILE * fptr;

main()
{
int ctr;
struct bookInfo books[3]; // Array of three structure variables

// Get the information about each book from the user
for (ctr = 0; ctr < 3; ctr++)
{
printf("What is the name of the book #%d?\n", (ctr+1)); 
gets(books[ctr].title);

puts("Who is the author? "); 
gets(books[ctr].author);

puts("How much did the book cost? "); 
scanf(" $%f", &books[ctr].price); 
puts("How many pages in the book? "); 
scanf(" %d", &books[ctr].pages);

getchar(); //Clears last newline for next loop
}

// Remember when typing your filename path to double up the 
// backslashes or C will think you are putting in a conversion character 

fptr = fopen("/tmp/BookInfo.txt","w");
// Test to ensure that the file opened
if (fptr == 0)
{
printf("Error--file could not be opened.\n"); 
exit (1);
}

// Print a header line and then loop through and print the info
// to your file, but this time this printout will be in your
// file and not on the screen.

fprintf(fptr, "\n\nHere is the collection of books: \n"); 
for (ctr = 0; ctr < 3; ctr++)
{
fprintf(fptr, "#%d: %s by %s", (ctr+1), books[ctr].title, books[ctr].author);
fprintf(fptr, "\nIt is %d pages and cost $%.2f", books[ctr].pages, 
               books[ctr].price);
fprintf(fptr, "\n\n");
}
fclose(fptr); // Always close your files 

return(0);
}

Warning : Opening a file in “w” mode overwrites an existing file with the same name. So if you run the previous program twice, the file will have only your data from the second run. If you want to build on to the file and keep the previous data, you need to open the file in “a” mode.

Use fgets() to read the contents of the file. fgets() is nothing more than a gets() that you can direct to a disk file. fgets() reads lines from a file into character arrays (or allocated heap memory pointed to with a character pointer).

Tip : Think of the f at the beginning of fputs() and fgets() as standing for file. puts() and gets() go to the screen and keyboard, respectively; fputs() and fgets() write and read their data from files.

Unlike gets(), fgets() requires that you specify a maximum length for the array you’re reading into. You might read past the end of the file (producing an error) if you’re not careful, so be sure to check for the location of the end of the file.

fgets() reads one line at a time. If you specify more characters to read in the fgets() than actually reside on the file’s line you’re reading, fgets() stops reading the line of data as long as the file’s lines end with a newline character. The previous program that created the bookinfo.txt file always wrote \n at the end of each line so that subsequent fgets() functions could read the file line by line.

The following program loops through a file and prints the info on the screen.

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

FILE * fptr;

main()
{
char fileLine[100]; // Will hold each line of input

fptr = fopen("/tmp/BookInfo.txt","r");
if (fptr != 0)
{
while (!feof(fptr))
{
fgets(fileLine, 100, fptr); 
if (!feof(fptr))
{
puts(fileLine);
}
}
}
else
{
printf("\nError opening file.\n");
}

fclose(fptr); // Always close your files 

return(0);
}

feof() returns a true condition if you just read the last line from the file. The feof() really isn’t needed in the previous program because we know exactly what the bookinfo.txt contains. But you should generally use feof() when reading from disk files. You often don’t know exactly how much data the file contains because other people using other programs might have added data to the file.

Note : In the fprintf() function, the file pointer goes at the beginning of the function. In the fgets() function, the file pointer goes at the end.

You also can use an fscanf() to read individual numeric values from a data file if you wrote the values with a corresponding fprintf().

You can add to a file by opening the file in append mode and outputting data to it.

/* The program opens the existing book info file 
   and adds a line to the end. */

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

FILE * fptr;

main()
{
fptr = fopen("/tmp/BookInfo.txt","a");
if (fptr == 0)
{
printf("Error opening the file! Sorry!\n"); 
exit (1);
}

// Adds the line at the end
fprintf(fptr, "\nMore books to come!\n");

fclose(fptr); // Always close your files 
return(0);
}

 

Data Structure < Prev                                                      Next > Disk files – Random access

Advertisements

2 comments

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s