8.4 随机访问(lseek)
输入/输出通常是顺序进行的:每次调用 read
和 write
进行读写的位置紧跟在前一次操作的位置之后
但是,有时候需要以任意顺序访问文件,系统调用 lseek
可以在文件中任意移动位置而不实际读写任何数据:
long lseek(int fd, long offset, int origin);
将文件描述符为 fd
的文件的当前位置设置为 offset
,其中,offset
是相对于 origin
指定的位置而言的
随后进行的读写操作将从此位置开始,origin
的值可以为 0
、1
或 2
,分别用于指定 offset
从文件开始、从当前位置或从文件结束处开始算起
例如,为了向一个文件的尾部添加内容(在 UNIX shell 程序中使用重定向符 >>
或在系统调用 fopen
中使用参数 a
)
则在写操作之前必须使用下列系统调用找到文件的末尾:
lseek(fd, 0L, 2);
若要返回文件的开始处(即反绕),则可以使用下列调用:
lseek(fd, 0L, 0);
请注意,参数 0L
也可写为 (long)0
,或仅仅写为 0
,但是系统调用 lseek
的声明必须保持一致
使用 lseek
系统调用时,可以将文件视为一个大数组,其代价是访问速度会慢一些
例如,下面的函数将从文件的任意位置读入任意数目的字节,它返回读入的字节数,若发生错误,则返回 -1
#include "syscalls.h"
/*get: read n bytes from position pos */
int get(int fd, long pos, char *buf, int n)
{
if (lseek(fd, pos, 0) >= 0) /* get to pos */
return read(fd, buf, n);
else
return -1;
}
lseek
系统调用返回一个 long
类型的值,此值表示文件的新位置,若发生错误,则返回 -1
标准库函数 fseek
与系统调用 lseek
类似,所不同的是,前者的第一个参数是 FILE *
类型,且在发生错误时返回一个非 0
值