When a person reads a book, her "location" in the book can be
specified by a page number (and even a line number or word number, at
finer levels of detail). Just so, it is possible (and often useful!) to
know the location, or file position, of a stream reading from or
writing to a file. And just as we sometimes want to know which chapter
a friend is currently reading in a book, or to recommend that he flip
backward or forward to an interesting passage, so it is frequently
useful to be able to change the current file position to access a more
interesting part of the file.
At the high level of the functions in this section, GNU treats all
streams as streams of characters -- even binary streams like the one
associated with the file numbers.dat in the example for
fread and fwrite. (See Block input and output.) This
means that the file position of any stream is a simple character count
-- file position 0 means that we are reading or writing the first
character in the file, file position 522 means that we are reading the
523rd character, and so on. (Just as with arrays in C, file positions
are zero-based.)
Not only does the file position of a stream describe where in the file
the stream is reading or writing, but reading or writing on the stream
advances the file position. During high-level access to a file, you can
change the file position at will. Any file that permits changing the
file position in an arbitrary way is called a random-access file.
(Many years ago, the people who invented computer jargon chose the word
"random" to be part of the phrase "random-access" because, from the
point of view of the computer, a random-access file can be read from or
written to at any location, as if at random. Of course, programmers are
not working randomly; they decide where their programs should read and
write. The term RAM for random-access memory comes from the
same source.)
The main high-level function to tell where the current file position is,
is called appropriately, ftell. It accepts a single parameter
-- a file stream -- and returns a long integer representing the file
position.1 (See libc, for
more information.)
The main function to seek a different file position is called
fseek. It accepts three parameters. The first parameter is the
stream in question, the second is a long integer offset, and the third
parameter is a constant that specifies whether the offset is relative to
the beginning of the file (SEEK_SET), to the current file
position (SEEK_CUR), or to the end of the file (SEEK_END).
The fseek function returns 0 if the operation was successful, or
a nonzero integer value otherwise. (A successful fseek operation
also clears the end-of-file indicator (see below), and discards the
results of ungetc. See ungetc.)
There is a simple macro called rewind that will take the file
pointer back to the beginning of the file. You must simply pass it the
stream that you want to rewind; it does not return a value. It is the
same as calling fseek on the stream with an offset of 0 and a
third parameter of SEEK_SET, except that it resets the error
indicator for the stream and, as mentioned, there is no return value.
An example of these functions will not be useful until we have
introduced single-character I/O. See getc and fgetc, if you want to
read a code example that uses the ftell, fseek, and
rewind functions.
Footnotes
Since the file position is a long integer, the length
of a file using one of these functions cannot be any greater than the
maximum value of a 32-bit long integer under GNU, plus one (since the
file position is zero-based) --- that is, such a file cannot be any more
than 2,147,483,648 bytes, or about two gigabytes long. If you need to
use longer files, you can use low-level file routines, which allow for
longer files and file positions through such 64-bit functions as
lseek64.