Moving Around Within Binary Files

One of the benefits of working with binary files is that it's very easy to move around within the binary data. When you open a file, C creates a marker pinpointing a location within this file. (This marker is commonly called a pointer but we don't want to confuse you since it's not the same kind of pointer you've been working with.) When you read from a file, the data is read and the marker is moved forward. When you write, the data is added at that location and, again, the marker is moved forward.

You can also move the marker directly to a specific point using fseek():

fseek(fp, offset, starting_point);

The first argument is our file pointer, which refers to an opened binary file. The second argument dictates how many bytes the virtual marker should move from the starting point. If the offset is positive, the marker is moved forward from the starting point. If the offset is negative, the marker is moved backwards from the starting point. The starting points themselves are specified using the constants or numeric equivalents listed in Table 12.3, and refer to the beginning of, the end of, or an arbitrary point in the file.

Table 12.3. These constants or their numeric equivalent are used with fseek() to move the marker around.
fseek() Starting Point Constants
ConstantNumericMeaning
SEEK_SET0LThe beginning of the file
SEEK_CUR1LThe current marker position within the file
SEEK_END2LThe end of the file

In this chapter's final example, the marker will be moved to a random point within the numbers file. From there, a number will be read and printed.

To navigate a binary file

1.
Create a new file or project in your text editor or IDE.

2.
Type the standard beginning lines of code (Script 12.7):

/* random_read.c - Script 12.7 */
#include <stdio.h>

Script 12.7. A random point in the data file is used to return a “lucky number.”


3.
Require two more standard libraries:

#include <stdlib.h>
#include <time.h>

Because this application will use the rand() function (as binary_write did), these extra libraries are necessary.

4.
Set the file path and name as a C preprocessor macro:

#define THEFILE
 "/Users/larry/Desktop/numbers.dat"

or

#define THEFILE "C:\Documents and
 Settings\Larry Ullman\Desktop\
 numbers.dat"

5.
Create a constant macro representing the number of items in the array:

#define ITEMS 50

6.
Begin the main function and create a file pointer:

int main (void) {
FILE *fp;

7.
Define the required variables:

int offset, number;

The first integer will be used as the offset: the location within the numbers file to move to. The second will store the read-in number value.

8.
Open the file for binary reading:

fp = fopen(THEFILE, "rb");

9.
Start a conditional based on the file pointer:

if (fp != NULL) {

10.
Determine a random offset value:

srand((unsigned)time(NULL));
offset = rand() % ITEMS;
offset *= sizeof(int);

The first line seeds the rand() function, using the timestamp returned by time(). The second line picks an arbitrary offset, as a random number up to the number of items stored. After this second line of code, offset will be equal to a number between 0 and 49, corresponding to the 50 items originally stored in the file (like an array, though, we begin counting at 0).

The third line multiplies the value of offset by the size of an integer. This is necessary because we need to specify the offset in bytes. For example, if the randomly generated value is 10, then the offset needs to be 40 bytes: 10 times sizeof(int), normally 4 bytes.

11.
Move to the random location and read in a number:

fseek (fp, offset, SEEK_SET);
fread (&number, sizeof(number),
 1, fp);

The first line moves the virtual marker offset bytes into the file, starting from the beginning of the file. The second line reads one block of data of sizeof(number) bytes and stores this in the number variable. Remember that the fread() function takes an address of a variable as its first argument, so &number is used (the memory address for the number variable).

12.
Print the number:

printf("Your lucky number is: %d.
",
 number);

Once the number has been retrieved, its value can be printed.

13.
Complete the fp conditional:

} else {
    printf ("The file could not
 be opened.
");
    return 1;
}

14.
Close the file:

if (fclose(fp) != 0) {
    printf ("The file could not
 be closed.
");
}

15.
Complete the main function:

    getchar();
    return 0;
}

16.
Save the file as random_read.c, compile, and debug as necessary.

17.
Run the application (Figure 12.13).

Figure 12.13. A random number is retrieved from the binary file and printed.


18.
Run the application again to see a different value (Figure 12.14).

Figure 12.14. Another execution of the same application retrieves a different random value.


✓ Tips

  • The fseek() function, like many functions, returns the value 0 if it worked and -1 otherwise.

  • The ftell() function returns the current location of the marker in the text file as a number of bytes.

  • The rewind() function moves the marker back to the beginning of the file.

  • The fseek() and ftell() functions will work on plain ASCII files as well, although doing so is trickier.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset