seek查找,lseek前后移动
(1)文件指针:打开之后,文件内存存着呢,读写时是对内存操作,是操作静态文件,只有保存时存静态文件,动态文件在内存中就是文件流的形式。
(2)文件流很长,我们当前操作的是哪个位置,也就是光标位置给我们提供即将操作的位置信息,GUI界面下告诉人操作位置,
内存中没有光标,是用指针存放的,文件管理表(在进程管理表内)中的指针,文件管理表中的一个成员(光标),文件指针是vnode中的一个元素,这个指针表示当前正在操作文件流的哪个位置,这个指针不能被直接访问,Linux系统中,用lseek来访问光标位置,让文件指针(光标)动,文件指针默认在打开时指向文件开头,write和read本身自带移动文件指针的功能,所以读写n个字节后,文件指针会自动向后移动
参数,fd文件描述符,offset偏移量,whence,参考位置是文件头/当前位置/文件尾
返回值是相对文件开头的偏移字节数
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
int fd = -1;//文件描述符
char buf[100] = {0};
char writebuf[20] = "i love linux LT.";
int ret = 0;
/*打开一个文件*/
fd = open("a.txt",O_RDWR);
if(-1 == fd)
{
printf("文件打开错误.\n");
}
else
{
printf("文件打开成功. fd = %d.\n",fd);
}
/*写文件*/
#if 0
ret = write(fd, writebuf, strlen(writebuf));
if(ret < 0)
{
printf("写入失败.\n");
}
else
{
printf("写入的字节数为:%d.\n",ret);
}
#endif
ret = lseek(fd, 3, SEEK_SET); //从开始移动4位,因为是从0开始计数的
/*读取文件的内容*/
#if 1
ret = read(fd, buf, 20);
if(-1 == ret)
{
printf("读取失败.\n");
}
else
{
printf("读出的字节数为:%d.",ret);
printf("文件内容为:[%s].",buf);
}
#endif
/*关闭一个文件*///关闭一般都不会出什么错误,所以返回值也不去管它了
close(fd);
return 0;
}
之前课程,我们写一个文件写入12个字节。想读出,但是读出的一片空白,原因是文件指针(光标)移动到文件末尾,导致什么东西也读不到。
用lseek计算文件的长度
Linux中并没有一个API能计算文件的长度,但是做项目时候,经常要知道文件得长度,此时可以用lseek来自己写一个函数,
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc,char *argv[])
{
int fd = -1;//文件描述符
int ret = -1;
if(argc != 2)
{
printf("usage: %s filename \n", argv[0]);//输入./a.out后面没跟文件名不行
_exit(-1);
}
/*打开一个文件*/
fd = open(argv[1], O_RDONLY);
if(-1 == fd)
{
printf("文件打开错误.\n");
}
else
{
printf("文件打开成功. fd = %d.\n",fd);
}
//打开文件之后,指正指向文件开头
//我们用lseek将文件指针移动到末尾,返回值就是文件的末尾的偏移量,就是文件的长度
ret = lseek(fd, 0, SEEK_END);
printf("文件长度是:%d./n", ret);
}
Linux下的代码是
root@ubuntu:/mnt/hgfs/05_winshare# gcc cal_len.c
root@ubuntu:/mnt/hgfs/05_winshare# ./a.out a.txt
文件打开成功. fd = 3.
root@ubuntu:/mnt/hgfs/05_winshare# ls -l
total 82415
-rwxrwxrwx 1 root root 991 Mar 17 22:21 a.c
-rwxrwxrwx 1 root root 7442 Mar 17 22:43 a.out
-rwxrwxrwx 1 root root 84380262 Sep 13 2017 arm-2009q3.tar.bz2
-rwxrwxrwx 1 root root 19 Mar 17 22:05 a.txt //此处显示改文件就是19个字节
-rwxrwxrwx 1 root root 1117 Mar 14 06:43 b.c
-rwxrwxrwx 1 root root 7610 Mar 14 06:44 b.out
-rwxrwxrwx 1 root root 753 Mar 17 22:43 cal_len.c
drwxrwxrwx 1 root root 0 Sep 26 06:05 s5pv210
这是为什么有的能显示中文,有的显示乱码。
lseek和空洞文件
空洞文件:文件中间有一段是空的
普通文件可以用lseek搞成空洞文件
我们打开一个文件,用lseek往后移动,就会弄成一个空洞文件
空洞文件平时不怎么用,这种技术是有用的,多线程操作文件是极其有用的,我们想能用更快的速度创建文件,如果从头开始一次构建,时间太长了,智能分段来完成,将文件分为多段,多线程操作一段的写入,用空洞文件的理论
文件是一个流,这个流是用文件指针指导的