用lseek( )查找
lseek( )系统调用能够对给定文件描述符引用的文件位置设定指定值。除了更新文件位置,没有其它的行为,并无论如何不初始化任何I/O。
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t pos, int origin);
origin参数可以为以下值之一:
- SEEK_CUR: 当前文件位置fd设置为当前值加上pos,pos可以为正/负/零
- SEEK_END: 当前文件位置fd设置为当前文件长度加上pos
- SEEK_SET: 当前文件位置fd设置为pos
例如,设置文件位置fd为1825:
off_t ret;
ret = lseek(fd, (off_t)1825, SEEK_SET);
if (ret == (off_t) -1)
/* error */
由于lseek( )返回更新过的文件位置,可以用SEEK_CUR和零值来确定文件当前位置:
int pos;
pos = lseek(fd, 0, SEEK_CUR);
if (pos == (off_t) - 1)
/* error */
else
/* 'pos' is the current position of fd */
-
文件末尾之后进行查找
lseek( )是可以在文件指针超过文件末尾之后进行查找的。例如以下代码将查找到fd对应的文件末尾之后1688个字节。
int ret;
ret = lseek(fd, (off_t) 1688, SEEK_END);
if (ret == (off_t) -1)
/* error */
- 对于读:没有影响,到最近文件位置的读请求会返回EOF。
- 对于写:会在新旧长度之间建立新的空间,被成为“空洞”(hole),并由零来填充。
空洞不占用任何物理上的磁盘空间,所以文件系统上所有文件的大小加起来可以超过磁盘的物理大小。带空洞的文件叫做“稀疏文件”。稀疏文件可以节省可观的空间并提升效率,因为操作那些空洞并不引发任何物理I/O。
定位读写
Linux提供了两种read( )和write( )的变体来替代lseek( ),每个调用都以需要读写的文件位置为参数。完成时,不修改文件位置。
- pread( ):
#define _XOPEN_SOURCE 500
#include <unistd.h>
ssize_t pread(int fd, void *buf, size_t count, off_t pos);
- pwrite( ):
#define _XOPEN_SOURCE 500
#include <unistd.h>
ssize_t pwrite(int fd, const void *buf, size_t count, off_t pos);
这两种定位读写都只能用于可以进行定位操作的文件描述符。
从语义角度来讲,相当于在调用read( )或write( )前使用lseek( )进行定位。区别在于:
- 这些调用更加简单易用,尤其是在文件中做反向移动和随机移动这种技巧性很强的操作时更是如此。
- 当操作完成时,不修改文件位置指针。
- 避免了任何在使用lseek( )时可能出现的潜在竞争。
截短文件
Linux提供了两个系统调用来截短文件:
- ftruncate( ):
#include <unistd.h>
#include <sys/types.h>
int ftruncate(int fd, off_t len);
- truncate( ):
#include <unistd.h>
#include <sys/types.h>
int truncate(const char *path, off_t len);
这两个系统调用都将文件截短到len指定的长度。ftruncate( )系统调用的参数是fd,而truncate( )的参数是路径名。
- 也可以将文件“截短”到比原长度更长。扩展出的字节将全部填充为零。
- 这两个操作均不修改当前文件位置。
网友评论