Getting and Setting the File Position Indicator

As data is read from a file, a file position indicator (which most C references call a “file pointer”) moves sequentially through the file’s data. As a review, three functions are available to adjust this offset:

  • The ftell() function returns the file position indicator’s current location as an offset within the file. (Post)
  • The fseek() function manipulates the file position indicator’s value, thrusting it to a specific location in the file. (Post)
  • The rewind() function resets the file position indicator back to the start of a file. (Post)

These functions are particularly useful when performing random file access, such as fetching structures saved in a file or any time a file contains data organized in discrete chunks.

Two more functions are available: fgetpos() and fsetpos(). The fgetpos() function returns the file position indicator’s location for an open file handle. The value is stored in a fpos_t structure. The fsetpos() function alters a file position’s location based on the values stored in a previously-created fpos_t structure. Here is the man page definition for fgetpos() and fsetpos():

int fgetpos(FILE *stream, fpos_t *pos);
int fsetpos(FILE *stream, const fpos_t *pos);

The first argument is an open file stream. The second argument is the address of an fpos_t variable. The return value is zero upon success, with -1 returned otherwise and the errno value set to indicate a specific error. Both functions are prototyped in the stdio.h header file.

Unlike the other file manipulation functions, the fpos_t structure is the key to using fgetpos() and fsetpos(). This structure isn’t manipulated directly as its two members are named differently depending on the platform. But that’s not the point of these functions, which are best put to use when the value of the file position indicator must be retained and restored later without knowing its specific location.

The following code uses these functions to read from the text file sonnet18.

2026_01_03-Lesson.c

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

int main()
{
    const char filename[] = "sonnet18.txt";
    FILE *fp;
    int count,ch;
    fpos_t pos;

    /* open the text file */
    fp = fopen(filename,"r");
    if( fp==NULL )
    {
        fprintf(stderr,"Unable to open %s\n",filename);
        exit(1);
    }
    printf("%s opened\n",filename);

    /* read 256 bytes */
    count = 0;
    while( count<256 )
    {
        ch = fgetc(fp);
        if( ch==EOF )
            break;
        putchar(ch);
        count++;
    }

    /* obtain the file position indicator position */
    puts("\n\n=== Getting file position indicator ===\n");
    fgetpos(fp,&pos);

    /* read another 256 bytes */
    count = 0;
    while( count<256 )
    {
        ch = fgetc(fp);
        if( ch==EOF )
            break;
        putchar(ch);
        count++;
    }

    /* reset the file position indicator */
    puts("\n\n=== Resetting file position indicator ===\n");
    fsetpos(fp,&pos);

    /* read the rest of the file */
    while( (ch=fgetc(fp)) != EOF )
        putchar(ch);

    /* clean-up */
    fclose(fp);
    printf("%s closed\n",filename);
    return 0;
}

After the file is open, a while loop fetches and outputs the first 256 characters from the file. Then the fgetpos() function obtains the file position indicator’s location and saves is in fpos_t variable pos‘s address: fgetpos(fp,&pos);

A second while loop reads another 256 characters, outputting each. But then the fsetpos() function is called to restore the file position indicator: fsetpos(fp,&pos); The rest of the file is then output.

Here’s a sample run:

sonnet18.txt opened
Shall I compare thee to a summer's day?
Thou art more lovely and more temperate.
Rough winds do shake the darling buds of May,
And summer's lease hath all too short a date.
Sometime too hot the eye of heaven shines,
And often is his gold complexion dimmed;

=== Getting file position indicator ===


And every fair from fair sometime declines,
By chance, or nature's changing course, untrimmed;
But thy eternal summer shall not fade,
Nor lose possession of that fair thou ow'st,
Nor shall death brag thou wand'rest in his shade,
When in eternal lines to T

=== Resetting file position indicator ===


And every fair from fair sometime declines,
By chance, or nature's changing course, untrimmed;
But thy eternal summer shall not fade,
Nor lose possession of that fair thou ow'st,
Nor shall death brag thou wand'rest in his shade,
When in eternal lines to Time thou grow'st.
  So long as men can breathe, or eyes can see,
  So long lives this, and this gives life to thee.
sonnet18.txt closed

Of course, for this example I know that the file position indicator is at 256 characters when it’s saved. But the true purpose of the fgetpos() and fsetpos() functions is to obtain and restore an unknown offset. And, yes, it’s valid to argue that ftell() and fseek() can be used in a similar manner. Even so, these functions are available as an alternative.

Leave a Reply