9.14. Random access functions
The file I/O routines all work in the same way; unless the user takes
explicit steps to change the file position indicator, files will be read and
written sequentially. A read followed by a write followed by a read (if the
file was opened in a mode to permit that) will cause the second read to
start immediately following the end of the data just written. (Remember
that stdio
insists on the user inserting a buffer-flushing
operation between each element of a read-write-read cycle.) To control this,
the Random Access functions allow control over the implied read/write
position in the file. The file position indicator is moved without the need
for a read or a write, and indicates the byte to be the subject of the next
operation on the file.
Three types of function exist which allow the file position indicator to be examined or changed. Their declarations and descriptions follow.
#include <stdio.h> /* return file position indicator */ long ftell(FILE *stream); int fgetpos(FILE *stream, fpos_t *pos); /* set file position indicator to zero */ void rewind(FILE *stream); /* set file position indicator */ int fseek(FILE *stream, long offset, int ptrname); int fsetpos(FILE *stream, const fpos_t *pos);
Ftell
returns the current value (measured in characters) of
the file position indicator if stream
refers to a binary
file. For a text file, a ‘magic’ number is returned, which may only
be used on a subsequent call to fseek
to reposition to the
current file position indicator. On failure, -1L
is returned
and errno
is set.
Rewind
sets the current file position indicator to the start
of the file indicated by stream
. The file's error indicator is
reset by a call of rewind
. No value is returned.
Fseek
allows the file position indicator for stream to be
set to an arbitrary value (for binary files), or for text files, only to
a position obtained from ftell, as follows:
- In the general case, the file position indicator is set
to offset bytes (characters) from a point in the file
determined by the value of
ptrname
.Offset
may be negative. The values ofptrname
may beSEEK_SET
, which sets the file position indicator relative to the beginning of the file,SEEK_CUR
, which sets the file position indicator relative to its current value, andSEEK_END
, which sets the file position indicator relative to the end of the file. The latter is not necessarily guaranteed to work properly on binary streams. - For text files,
offset
must either be zero or a value returned from a previous call toftell
for the same stream, and the value ofptrname
must beSEEK_SET
. Fseek
clears the end of file indicator for the given stream and erases the memory of anyungetc
. It works for both input and output.- Zero is returned for success, non-zero for a forbidden request.
Note that for ftell
and fseek
it must be
possible to encode the value of the file position indicator into
a long
. This may not work for very long files, so the Standard
introduces fgetpos
and fsetpos
which have been
specified in a way that removes the problem.
Fgetpos
stores the current file position indicator for
stream in the object pointed to by pos. The value stored is ‘magic’
and only used to return to the specified position for the same stream
using fsetpos.
Fsetpos
works as described above, also clearing the stream's
end-of-file indicator and forgetting the effects of any ungetc
operations.
For both functions, on success, zero is returned; on failure, non-zero is returned and errno is set.
9.14.1. Error handling
The standard I/O functions maintain two indicators with each open stream to show the end-of-file and error status of the stream. These can be interrogated and set by the following functions:
#include <stdio.h> void clearerr(FILE *stream); int feof(FILE *stream); int ferror(FILE *stream); void perror(const char *s);
Clearerr
clears the error and EOF indicators for the
stream.
Feof
returns non-zero if the stream
's EOF
indicator is set, zero otherwise.
Ferror
returns non-zero if the stream's error indicator is
set, zero otherwise.
Perror
prints a single-line error message on the program's
standard output, prefixed by the string pointed to by s
,
with a colon and a space appended. The error message is determined by
the value of errno and is intended to give some explanation of the
condition causing the error. For example, this program produces the
error message shown:
#include <stdio.h> #include <stdlib.h> main(){ fclose(stdout); if(fgetc(stdout) >= 0){ fprintf(stderr, "What - no error!\n"); exit(EXIT_FAILURE); } perror("fgetc"); exit(EXIT_SUCCESS); } /* Result */ fgetc: Bad file numberExample 9.8
Well, we didn't say that the message had to be very meaningful!