lseek的学习记录 移动文件指针用的

关于流的概念

文件读写的时候是一个一个字符读写的,然后这些按着顺序读写的字符就构成了字符流,这些字符被动态连续的处理,形成了流。

文件指针

在windows操作文件的时候,会有一个光标来显示当前要操作的位置,这个位置就是文件指针。
在linux中,文件指针不能被直接操作,可以利用read、write这两个函数进行间接操作,也可以用lseek这个函数来进行人为更改文件指针的位置

off_t lseek(int fd, off_t offset, int whence);

这个是lseek的原型,使用这个API的话需要传三个参数:
第一个是fd文件描述符;
第二个是偏移量,用来给你设置你要偏移的字符位数;
第三个是whence参数
可以选择SEEK_SET、SEEK_CUR、SEEK_END这三个

SEEK_SET
The file offset is set to offset bytes.
这个表示把文件指针放在你设置的偏移量的位置,这个偏移量是相对于文件开头而言,
比如说你设置了2,则文件指针就在第二个字符的后面,
像Windows下的光标,在第二个字符后面“一闪一闪”。

SEEK_CUR
The  file  offset  is  set  to its current location plus offset bytes.
这个表示文件指针的位置设置在当前位置加上你设置的offset值的位置。比如说你的
当前文件指针在第三个字符后面,你设置了offset值是2,那么最终的文件指针就在3+2=5
在第五个字符后面。

SEEK_END
The file offset is set to the size  of  the  file  plus  offset bytes.
这个表示文件指针的位置是文件末尾的位置加上设置的offset值的和的位置。
在terminal上面打印出来的话看不了到底是不是有移动,
但是用vim打开的话可以很明显看到有两个@@多了出来,因为我设置的offset值是2.

plus.我在测试的时候发现,如果在Windows下先编辑文件,
然后再通过设置SEEK_END这些的话,文件加上去的地方还是在末尾的,
如果在linux下用vim打开过的话呢就会出现自动换行的现象。

测试的时候发现如果编辑文件在vim打开过之后,后面执行了都会自动换行。

用lseek来计算文件长度

  • 用lseek计算文件长度的原理就是利用lseek函数的返回值特性,它的返回值是返回当前文件指针相对于文件第一个字符的偏移量,所以用到SEEK_END的特性,把文件指针移动到末尾,同时偏移量设置为0,即文件指针被移动的位置是末尾位置+0也就是末尾的位置了。
#include<stdio.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <unistd.h>

int main(int argc,char *argv[])
{
	
	//打开文件
	if(argc != 2)
	{
		printf("用法:%s 文件名\n",argv[0]);
		return -1;
	}
	int fd = -1;
	fd = open(argv[1],O_RDWR);
	
	
	if (-1 == fd)
	{
		printf(" file open fail\n");
	}
	else
	{
		printf("file open success , fd = %d \n",fd);
	}
	//计算长度
	int ret = -1;
	ret = lseek(fd ,0,SEEK_END);
	printf("文件长度为%d字节\n", ret);
	
	
#if 0
	
	//写文件
	int w_ret = -1;
	char buf2 [] = "a22";
	w_ret = write(fd,buf2,sizeof(buf2));
	if (-1 == w_ret)
	{
		printf("write fail\n");
	}
	else
	{
		printf("write success,写入了%d个字节\n",w_ret);
		printf("w_ret = %d\n",w_ret);
	}
	

#endif

#if 0
	//读取文件
	char buf[100] = {0};
	int ret = -1;
	ret = read(fd,buf, 20);
	if (-1 == ret)
	{
		printf("read file fail");
	}
	else
	{	
		printf("实际读取了%d字节\n",ret);
		printf("文件内容是\n[\n%s]\n",buf);
		printf("ret = %d\n",ret);
	}	
#endif
	close(fd);

	return 0;
}

  • 这里涉及到了argc和argv的使用百度百科argc argv
    argc代表的是变量的个数,是int型的,argv是一个指针数组,v-vector,是char*型的专门用来放指向这些变量的指针变量的,
    argc可以说包含两部分,第一部分是程序名或者程序运行的全路径名,这也算一个变量名
    第二部分就是传进去的变量了,所以从argc[0]----程序名,argc[1]------传进去的第一个变量……以此类推,argv[0]、argv[1]……也是以此对应来理解。

  • 下面一部分代码是课件的,他把计算部分封装成了一个函数

int cal_len(const char *pathname)
{
	int fd = -1;		// fd 就是file descriptor,文件描述符
	int ret = -1;
	
	// 第一步:打开文件
	fd = open(pathname, O_RDONLY);
	if (-1 == fd)		// 有时候也写成: (fd < 0)
	{
		//printf("\n");
		perror("文件打开错误");
		// return -1;
		return -1;
	}
	//else
	//{
		//printf("文件打开成功,fd = %d.\n", fd);
	//}
	
	// 此时文件指针指向文件开头
	// 我们用lseek将文件指针移动到末尾,然后返回值就是文件指针距离文件开头的偏移量,也就是文件的长度了
	ret = lseek(fd, 0, SEEK_END);
	
	return ret;
}



int main(int argc, char *argv[])
{
	int fd = -1;		// fd 就是file descriptor,文件描述符
	int ret = -1;
	
	if (argc != 2)
	{
		printf("usage: %s filename\n", argv[0]);
		_exit(-1);
	}
	

	printf("文件长度是:%d字节\n", cal_len(argv[1]));
	
	
	
	
	return 0;
}
  • 注意传参的形式对应,char*的话就要传char *,open了之后记得最后close (fd),它这里没有写。

用lseek构建空洞文件

原理就是利用lseek的SEEK_SET,把文件指针移动到当前位置加上你设置的offset位置的和的位置,一般open一个文件的时候,没有特殊设置,文件指针都会在最前面。例如这时候offset设置10,然后再write一次的话,中间就有一段10个字节的空洞位置,也就是构建了一个空洞文件。

lseek(fd, 10, SEEK_SET);

引用课上的说法,空洞文件的方法对多线程共同操作文件极其有用,就像以前flashget那样下载,有一个一个下载点,最终连成一片那样。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值