必威体育Betway必威体育官网
当前位置:首页 > IT技术

C语言:lseek函数-----改变文件偏移量

时间:2019-11-07 22:43:25来源:IT技术作者:seo实验室小编阅读:62次「手机版」
 

lseek

1.文件偏移

  • 通常调用read或write每读写一个文件,就会改变文件的读写位置。在linux中同样可以使用lseek函数来修改文件偏移量,即读写位置。
  • 标准C库的fseek函数和系统函数lseek比较类似,fseek函数也可以移动当前读写位置(或者叫偏移量),其实fseek就是对lseek系统函数封装后实现的,快速回忆一下之前学习的fseek函数的作用及常用参数。

lseek函数

  • 函数原型:
#include <sys/types.h>
#include <unistd.h>
off_t  lseek(int fd, off_t offset, int whence);
  • 参数说明:

  • fd : 文件描述符

  • offset : 文件偏移量(offset为负值表示往前偏移,正值则表示往后偏移)

  • whence : 偏移位置(SEEK_SET,SEEK_CUR,SEEK_END)

      1. SEEK_SET表示从文件开头位置往后移动offset个字节,且offset只能为正数,如果offset为负数是没有意义的。

      2. SEEK_CUR表示从当前文件的位置往前或往后移动offset个字节,如果offset为正数则表示往后移动,为负数则表示往前移动。

      3. SEEK=END表示从文件末尾的位置往前或往后移动offset个字节,如果offset为正数则表示往后移动为负数则表示往前移动。

      在这里插入图片描述


这里给一些lseek函数的一些例子,注释说明了文件偏移量到的具体位置:

  lseek(fd , 0 , SEEK_SET); //文件开始位置

  lseek(fd , 0 , SEEK_END); //文件末尾位置

  lseek(fd , 10 , SEEK_END); //从文件末尾往后移动10个字节

  lseek(fd , -10 , SEEK_END); //从文件末尾往前移动10个字节

  lseek(fd , 100 , SEEK_SET); //从文件开始往后移动100个字节

返回值说明:

  成功返回文件当前读写位置相对于文件开始位置的偏移量(字节数),如果文件读写的位置是在末尾的话,返回值就是文件头与文件尾之间的字节数,也就是文件大小。失败返回-1并设置errno

  

注意几点:

  1. 如果文件偏移量往回超出文件头位置,则返回-1,文件指针不变,还是处于原来的位置。

  2. lseek并不适用与所有的文件类型,也就是说在管道,FIFO,socket或终端不能使用lseek函数,一旦调用将会失败,并设置errno为EPIPE。

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

int main(void) 
{
	int fd, n;
	char buf[] = "hello world test \n";
	char ch;

	fd = open("test.txt", O_RDWR|O_CREAT, 0644);
	if(fd < 0)
	{
		pERROR("open lseek.txt error");
		exit(1);
	}
	//使用fd对打开的文件进行写操作,写完后文件指针位置位于文件结尾处
	write(fd, buf, strlen(buf));   
	/*
    注意:读和写操作使用同一偏移位置,由于文件指针位于末尾,因此后面的read就会读不到数据了
	这一行的目的是把文件指针移动到文件头位置,这样下面的代码就能读到数据了
	*/
	lseek(fd , 0 , SEEK_SET);
	if(n == -1)
	{
	    perror("lseek fail");
	    exit(1);
	}
	//lseek移到文件开头,read就能读取到数据了
	while((n = read(fd, &ch, 1)))
	{
		if(n < 0)
		{
			perror("read error");
			exit(1);
		}
		//将文件内容按字节读出,写到屏幕
		write(STDOUT_FILENO, &ch, n);  
	}
	close(fd);
	return 0;
}
  • 通过lseek计算文件大小
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

int main(void)
{
	int fd;
	char buf[] = "hello world"; 
	fd = open("lseek.txt", O_RDWR | O_CREAT, 0664);
	if(fd < 0){
		perror("open lseek.txt error");
		exit(1);
	}
	write(fd , buf , strlen(buf));
	//lseek函数会从起始位置开始算到文件末尾,就能求出文件的长度了
	int len = lseek(fd, 0, SEEK_END);
	if(len == -1){
		perror("lseek error");
		exit(1);
	}
	//lseek函数的返回值就是文件的大小
	printf("file len = %d\n", len);
	close(fd);
	return 0;
}

  • 扩展文件大小

    lseek函数还可用于扩展文件大小,但是单独使用lseek是不能达到扩展文件的,还必须发生一次IO操作才能扩展文件大小。

#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|O_TRUNC, 0644);
        if(fd < 0){
                perror("open lseek.txt error");
                exit(1);
        }

        //扩展文件大小100字节
        int ret = lseek(fd, 100, SEEK_SET);
        if (ret == -1) {
                perror("lseek error");
                exit(1);
        }
        //发生一次I/O操作
        write(fd, "\0", 1);  
        //位移到文件尾部
        int len = lseek(fd, 0, SEEK_END);
        printf("file size is %d\n", len);
        close(fd);
        return 0;
}

文章最后发布于: 2018-12-17 21:24:22

相关阅读

VITAL: Visual Tracking via Adversarial Learning 阅

本文概览 本文是一篇很不错的关于目标跟踪算法的文章,收录于CVPR2018。 论文链接:https://arxiv.org/pdf/1804.04273.pdf 本文主要

CableModem原理

Cable Modem的一些参数321物理层 下行通道的频率范围为88~860MHz,每个通道的带宽为6MHz(NTSC 6 G-MHz,PAL 8MHz),采用64QAM或2

从乐视又收购FF.com来看 企业还有什么理由不提前布局

昨日,域名圈的大佬徐俊发了这么一个朋友圈,大概意思是乐视现在对域名非常重视,去年从美国银行买了FF.com,给电动汽车公司Faraday Futu

JavaScript问题:一张纸的厚度是0.0001米,将纸对折,对折多

使用JavaScript 使用for 循环: var mountain = 8848; var paper = 0.0001; for (var i = 1; i < 100; i++) { paper *= 2;

oracle中的greatest 函数和 least函数

greatest (max(one),max(two),max(three))求多列的最大值,oracle中的greatest 函数 已知表TB的数据如下 SQL> select * from tb; 

分享到:

栏目导航

推荐阅读

热门阅读