对于每个打开的文件,系统都会记录它的读写位置偏移量,我们也把这个读写位置偏移量称为读写偏移量,Linux 中可使用系统函数 lseek 来修改文件偏移量 ( 读写位置 )
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
        fd 文件描述符。
        offset 偏移量,以字节为单位。
        whence 用于定义参数 offset 偏移量对应的参考值,该参数为下列其中一种(宏定义):
        SEEK_SET:读写偏移量将指向 offset 字节位置处(从文件头部开始算);
        SEEK_CUR:读写偏移量将指向当前位置偏移量 + offset 字节位置处, offset 可以为正、也可以为负,如果是正数表示往后偏移,如果是负数则表示往前偏移;
        SEEK_END:读写偏移量将指向文件末尾 + offset 字节位置处,同样 offset 可以为正、也可以为负,如果是正数表示往后偏移、如果是负数则表示往前偏移。
        返回值:成功将返回从文件头部开始算起的位置偏移量(字节为单位),也就是当前的读写位置;发生错误将返回-1,并设置errno值。


应用场景1. 文件的“读”、“写”使用同一偏移位置。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

int main(void) 
{
	int fd, n;
	char msg[] = "It's a test for lseek\n";
	char ch;

	fd = open("lseek.txt", O_RDWR|O_CREAT, 0644);
	if(fd < 0){
		perror("open lseek.txt error");
		exit(1);
	}

	write(fd, msg, strlen(msg));    //使用fd对打开的文件进行写操作,问价读写位置位于文件结尾处。

	lseek(fd, 0, SEEK_SET);         //修改文件读写指针位置,位于文件开头。 注释该行会怎样呢?

	while((n = read(fd, &ch, 1))){
		if(n < 0){
			perror("read error");
			exit(1);
		}
		write(STDOUT_FILENO, &ch, n);   //将文件内容按字节读出,写出到屏幕
	}

	close(fd);

	return 0;
}

应用场景2:使用lseek获取文件大小

通过 lseek 获取文件的大小: lseek(fd, 0, SEEK_END);
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

int main(void)
{
	int fd;
	fd = open("lseek.txt", O_RDWR);
	if(fd < 0){
		perror("open lseek.txt error");
		exit(1);
	}

	int len = lseek(fd, 0, SEEK_END);
	if(len == -1){
		perror("lseek error");
		exit(1);
	}
	printf("file size = %d\n", len);
	close(fd);
	return 0;
}

应用场景3:使用lseek拓展文件大小:要想使文件大小真正拓展(比较野,不建议),必须引起IO操作。(即要write入)

 使用 lseek 拓展文件:write 操作才能实质性的拓展文件。单 lseek 是不能进行拓展的。

一般:write(fd, "a", 1)

od -tcx filename 查看文件的 16 进制表示形式
od -tcd filename 查看文件的 10 进制表示形式
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
int main(void)
{
	int fd = open("./ysy.c",O_RDWR);
	if(fd == -1)
	{
		perror("open error");
		exit(1);
	}
	int len = lseek(fd, 100, SEEK_END);
	if(len == -1)
	{
		perror("lseek error");
		exit(1);
	}
	printf("file size=%d\n",len);
	int ret = write(fd,"\0",1);
	printf("%d\n",ret);
	close(fd);
	return 0;
}

使用 truncate 函数,直接拓展文件。    int ret = truncate

#include <unistd.h>
#include <sys/types.h>
int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);
        这两个函数的区别在于:ftruncate() 使用文件描述符 fd 来指定目标文件,而 truncate() 则直接使用文件路径 path 来指定目标文件,其功能一样。这两个函数都可以对文件进行截断操作,将文件截断为参数 length 指定的字节长度,什么是截断?如果文件目前的大小大于参数 length 所指定的大小,则多余的数据将被丢失,类似于多余的部分被“砍”掉了;如果文件目前的大小小于参数 length 所指定的大小,则将其进行扩展,对扩展部分进行读取将得到空字节"\0"
        使用 ftruncate()函数进行文件截断操作之前,必须调用 open() 函数打开该文件得到文件描述符,并且必 须要具有可写权限,也就是调用 open() 打开文件时需要指定 O_WRONLY O_RDWR
        调用这两个函数并不会导致文件读写位置偏移量发生改变,所以截断之后一般需要重新设置文件当前的读写位置偏移量,以免由于之前所指向的位置已经不存在而发生错误(譬如文件长度变短了,文件当前所指向的读写位置已不存在)。
        调用成功返回 0 ,失败将返回 -1 ,并设置 errno 以指示错误原因。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void) {
     int fd;
     /* 打开 file1 文件 */
     if (0 > (fd = open("./file1", O_RDWR))) {
         perror("open error");
         exit(-1);
     }
 /* 使用 ftruncate 将 file1 文件截断为长度 0 字节 */
     if (0 > ftruncate(fd, 0)) {
         perror("ftruncate error");
         exit(-1);
     }
 /* 使用 truncate 将 file2 文件截断为长度 1024 字节 */
     if (0 > truncate("./file2", 1024)) {
         perror("truncate error");
        exit(-1);
     }
 /* 关闭 file1 退出程序 */
     close(fd);
     exit(0);
}

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐