Seeking Within a File

The last example showed a program that sequentially read through the /etc/motd file, copying it to standard output. Sometimes it is necessary to access portions of a file randomly. Perhaps your file represents a series of a million fixed-length records that must be retrieved at random. UNIX provides this functionality in the form of the lseek(2) function.

Applying lseek(2)

The lseek(2) function is actually a dual-purpose function. It not only allows the program to seek a specified offset within the open file, but the program can also find out what the current offset is, within the specified file. The function synopsis for lseek(2) is as follows:

#include <sys/types.h>
#include <unistd.h>

off_t lseek(int fildes, off_t offset, int whence);

This function requires a file descriptor in the first argument and then a file offset and an integer value named whence. The combination of arguments offset and whence indicates how the seek is to be performed within the file.

Upon successful completion of the seek operation, the new file offset is returned. If the operation fails, an (off_t)-1 value is returned, with errno holding the reason for the error. Note that this function call does not return the error EINTR. The error code ESPIPE is returned if the file descriptor is for a non-seekable device.

Values for whence are provided in Table 4.2. These values are defined in the include file <unistd.h>.

Table 4.2. Values for lseek(2) Argument whence
C Macro Meaning
SEEK_SET The file offset is set to offset bytes.
SEEK_CUR The file offset is set to its current location plus offset bytes.
SEEK_END The file offset is set to the size of the file plus offset bytes.

The value SEEK_SET allows you to set an absolute file position, while SEEK_CUR lets you adjust your offset relative to your current offset. The SEEK_END value is usually used to position at the end of the file but, by applying a negative offset, you can establish some other position.

Figure 4.1. lseek(2) changes to a file offset.


To establish a new file position at the offset of 1024, you would code

off_t new_off;         /* New offset */
int fd;                /* File descriptor */

new_off = lseek(fd,1024,SEEK_SET);
if ( new_off == (off_t)(-1) )
    /* Report error */

To find out what your current file offset is, you could use the following form of the lseek(2) call, which does not change your current position:

off_t offset;          /* File offset */
int fd;                /* File descriptor */

offset = lseek(fd,0,SEEK_CUR);

In this form of the call, you seek 0 bytes from the current position, which changes nothing. However, the lseek(2) function tells you in the return value what the unchanged file offset is.

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

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