文件打开时,会将文件偏移量设置为指向文件开始,以后每次读写将自动对其进行调整,以指向已读或已写数据后的下一字节。这一点,与标准I/O中的流的定位是一样的。
#include <sys/types.h> #include <unistd.h> off_t lseek(int fd, off_t offset, int whence);点击复制复制失败已复制
参数 fd
指代已打开的文件,参数 whence
用来设置定位的位置,可以设置 3
种模式: SEEK_SET
、 SEEK_CUR
和 SEEK_END
,分别表示定位到文件的开始处、当前位置以及末尾。 offset
依然表示在第三个参数定位的基础上再次发生偏移。函数的返回值为当前定位的位置相对于文件开始处的偏移量。
示例
文件数据的复制
从一个文件(源文件)中读取最后 10KB
的数据并复制到另一个文件中(目标文件)。源文件以只读的方式打开,目标文件以只写的方式打开,若目标文件不存在,可以创建并设置权限的初始值为 0664
(文件所属用户可读写,文件所属组和其他用户只能读)。
#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #define BUFFER_SIZE 1024 #define SRC_FILE "src_file" #define DEST_FILE "dest_file" #define OFFSET 10240 #define errlog(errmsg) \ perror(errmsg); \ printf("--%s--%s--%d--\n", __FILE__, __FUNCTION__, __LINE__); \ return -1; int main(int argc, const char *argv[]) { int fds, fdd; unsigned char buf[BUFFER_SIZE]; ssize_t read_led; if ((fds = open(SRC_FILE, O_RDONLY)) < 0) { errlog("open error"); } if ((fdd = open(DEST_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0664)) < 0) { errlog("open error"); } lseek(fds, -OFFSET, SEEK_END); while ((read_led = read(fds, buf, sizeof(buf))) > 0) { write(fdd, buf, read_led); } close(fds); close(fdd); return 0; }点击复制复制失败已复制
文件读写位置的定位确定之后,程序就可以通过定位操作完成文件数据的截取或合并等问题。
生成空洞文件
在笔记文件的长度中介绍了空洞文件,这里我们演示如何生成一个空洞文件。
#include <fcntl.h> #include <stdio.h> #include <string.h> #include <sys/types.h> #include <unistd.h> #define N 32 int main(int argc, const char *argv[]) { int fd; char buf1[N] = "abcdefg"; char buf2[N] = "hijklmn"; fd = open("test.txt", O_RDWR | O_CREAT | O_TRUNC, 0664); write(fd, buf1, strlen(buf1)); lseek(fd, 65536, SEEK_CUR); write(fd, buf2, strlen(buf2)); return 0; }点击复制复制失败已复制
上述代码通过在文件数据末尾,进行重新读写位置的定位(代码选择偏移 65536
字节),偏移之后再写入数据,则会在中间形成没有数据的空洞。
编译运行,查看生成的 test.txt
文件:
$ gcc main.c && ./a.out $ od -c test.txt 0000000 a b c d e f g \0 \0 \0 \0 \0 \0 \0 \0 \0 0000020 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 * 0200000 \0 \0 \0 \0 \0 \0 \0 h i j k l m n 0200016点击复制复制失败已复制
提示
test.txt
文件在系统中显示为 65.5kB
。