C69. C File Positioning

File Positioning
int fgetpos(FILE * restrict stream,fpost * restrict pos);
int fseek(FILE *stream, long int offset, int whence);
int fsetpos(FILE *stream, const fpos_t *pos);
 long int ftell (FILE *stream) void rewind(FILE *stream);
Every stream has an associated file position. When a tile is opened, the file posi­tion is set at the beginning of the file. (If the tile is opened in "append" mode, how­ever, the initial tile position may be at the beginning or end of the tile, depending on the implementation.) Then, when a read or write operation is performed, the file position advances automatically, allowing us to move through the file in a sequen­tial manner.

Although sequential access is fine for many applications, some programs need the ability to jump around within a file, accessing some data here and other data there. If a file contains a series of records, for example, we might want to jump directly to a particular record and read it or update it. supports this form of access by providing five functions that allow a program to determine the current lile position or to change it.

The f seek function changes the file position associated with the first argu­ment (a file pointer). The third argument specifies whether the new position is to be calculated wilh respect to the beginning of the file, the current position, or the end of the file. defines three macros for this purpose:
SEEK_SET Beginning of file
SEEK_CUR Current file position
SEEK END End of file
The second argument is a (possibly negative) byte count. To move to the beginning of a tile, for example, the seek direction would be SEEK_SET and the byte count would be zero:
fseek(fp, OL, SEEK_SET);  /* moves to beginning of file */
To move to the end of a file, the seek direction would be SEEK_END:
fseek(fp, OL, SEEK_END); /* moves to end of file */
To move back 10 bytes, the seek direction would be SEEK CUR and the byte count would be -10:
fseek(fp, -10L, SEEK_CUR); /* moves back 10 bytes */
Note that the byte count has type long int, so I've used OL and -10L as argu­ments. (0 and -10 would also work, of course, since arguments are converted to the proper type automatically.)

Normally, fseek returns zero. If an error occurs (the requested position doesn't exist, for example), fseek returns a nonzero value.

The file-positioning functions are best used with binary streams, by the way. C doesn't prohibit programs from using them with text streams, but care is required because of operating system differences, fseek in particular is sensitive to whether a stream is text or binary. For text streams, either (1) offset (f seek's second argument) must be zero or (2) whence (its third argument) must be SEEK_SET and offset a value obtained by a previous call of f tell. (In other words, we can only use fseek to move to the beginning or end of a text stream or to return to a place that was visited previously.) For binary streams, fseek isn't required to support calls in which whence is SEEK_END.

The f tell function returns the current file position as a long integer. (If an error occurs, f tell returns -1L and stores an error code in errno.) The value returned by f tell may be saved and later supplied to a call of fseek, making it possible to return to a previous file position:
long file_pos;
file_pos = ftell(fp); /* saves current position */
fseek(fp, file_pos, SEEK_SET); /* returns to old position */
If fp is a binary stream, the call ftell (fp) returns the current file position as a byte count, where zero represents the beginning of the file. If fp is a text stream, however, ftell (fp) isn't necessarily a byte count. As a result, it's best not to perform arithmetic on values returned by ftell.

Rewind Function

The rewind function sets the file position at the beginning. The call rewind (fp) is nearly equivalent to fseek (fp, OL, SEEK_SET). The dif­ference? rewind doesn't return a value but does clear the error indicator for f p.

fseek and ftell have one problem: they're limited to files whose posi­tions can be stored in a long integer. For working with very large files, C pro­vides two additional functions: fgetpos and fsetpos. These functions can handle large tiles because they use values of type f pos_t to represent tile posi­tions. An fpos_t value isn't necessarily an integer: it could be a structure, for instance.

The call fgetpos (fp, &cfile_pos) stores the file position associated with fp in the f ile_pos variable. The call fsetpos (fp, &f ile_pos) sets the file position for fp to be the value stored in f ile pos. (This value must have been obtained by a previous call of fgetpos.) If a call of fgetpos or fsetpos fails, it stores an error code in errno. Both functions return zero when they suc­ceed and a nonzero value when they fail.

Here's how we might use fgetpos and fsetpos to save a file position and return to it later:
fpos_t file_pos;
fgetpos(fp, &file_pos); /* saves current position */
fsetpos(fp, &file_pos); /* returns to old position */

No comments: