所有打开的文件都有一个当前文件偏移量(current file offset),以下简称为 cfo。cfo 通常是一个非负整数,用于表明文件开始处到文件当前位置的字节数。读写操作通常开始于 cfo,并且使 cfo 增大,增量为读写的字节数。文件被打开时,cfo 会被初始化为 0,除非使用了O_APPEND 。

使用 lseek 函数可以改变文件的 cfo 。

#include <unistd.h>

#include <sys/types.h>

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

  返回值:新的偏移量(成功),-1(失败)

参数 offset 的含义取决于参数 whence:

1. 如果 whence 是 SEEK_SET,文件偏移量将被设置为 offset。
    2. 如果 whence 是 SEEK_CUR,文件偏移量将被设置为 cfo 加上 offset,
       offset 可以为正也可以为负。
    3. 如果 whence 是 SEEK_END,文件偏移量将被设置为文件长度加上 offset,
       offset 可以为正也可以为负。

SEEK_SET、SEEK_CUR 和 SEEK_END 是 System V 引入的,在这之前使用的是 0、1 和 2。

lseek 的以下用法返回当前的偏移量:

off_t    currpos;
        currpos = lseek(fd, 0, SEEK_CUR);

这个技巧也可用于判断我们是否可以改变某个文件的偏移量。如果参数 fd(文件描述符)指定的是 pipe(管道)、FIFO 或者 socket,lseek 返回 -1 并且置 errno 为ESPIPE。

对于普通文件(regular file),cfo 是一个非负整数。但对于特殊设备,cfo有可能是负数。因此,我们不能简单地测试 lseek 的返回值是否小于 0 来判断 lseek 成功与否,而应该测试 lseek 的返回值是否等于 -1 来判断 lseek 成功与否。

lseek 仅将 cfo 保存于内核中,不会导致任何 I/O 操作。这个 cfo 将被用于之后的读写操作。

如果 offset 比文件的当前长度更大,下一个写操作就会把文件“撑大(extend)”。这就是所谓的在文件里创造“空洞(hole)”。没有被实际写入文件的所有字节由重复的 0 表示。空洞是否占用硬盘空间是由文件系统(file system)决定的。

以下程序创建一个有空洞的文件:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>

void myRead(int fd)
{
  int i = 0;
  int rv = 0;
  char buf[64];
  memset(buf, '\0', 64);
  int len = 0;
  len = lseek(fd, 0, SEEK_END);
  printf("len=%d\n", len);
  len = lseek(fd, 0, SEEK_CUR);
  printf("len=%d\n", len);
  lseek(fd, 0, SEEK_SET);

  rv = read(fd, buf, 64);
  if(rv != -1)
  {
    if(rv < 64)
    {
      printf("finished read the file\n");
      for(i=0; i<rv; i++)
      {
        printf("%c", buf[i]);
      }
    }
  }

  printf("\n");

}

int main()
{
  int rv = 0;
  int fd = 0;
  fd = open("test.txt", O_RDWR|O_CREAT|O_TRUNC, S_IRWXU);

  char buf[64] = "wow so crazy!";

  rv = write(fd, buf, strlen(buf));

  myRead(fd);

  //设置文件偏移量超出文件大小

  lseek(fd, 10, SEEK_END);

  write(fd, buf, strlen(buf));

  myRead(fd);

  close(fd);

  return 0;
}

使用指令 od -c test.txt 查看空洞

转自:http://blog.csdn.net/songyang516/article/details/6779950

lseek函数的更多相关文章

  1. 《UNIX环境高级编程》笔记--read函数,write函数,lseek函数

    1.read函数 调用read函数从文件去读数据,函数定义如下: #include <unistd.h> ssize_t read(int filedes, void* buff, siz ...

  2. 文件I/O(不带缓冲)之lseek函数

    每个打开的文件都有一个与其相关联的“当前文件偏移量”(current file offset).它通常是一个非负整数,用以度量从文件开始处计算的字节数.通常,读.写操作都从当前文件偏移量处开始,并使偏 ...

  3. lseek()函数

    lseek()有个特殊的用途,确定文件是常规文件还是设备.<pre lang="c" escaped="true">off_t currpos;ou ...

  4. 关于位图读取函数int Load_Bitmap_File的lseek问题。

    事情是这样的,本人在编译3D游戏编程大师技巧中的程序是遇到了一个关于位图读取函数int Load_Bitmap_File的lseek问题. 我使用以下位图读取函数读取位图事报错如下: int Load ...

  5. linux系统编程之lseek帮助文档

    通过man 2 lseek可以查看linux中的系统函数lseek函数的帮助文档,为了更好的学习,我把这些重要内容翻译过来 NAME lseek - reposition read/write fil ...

  6. linux设备驱动归纳总结(三):3.设备驱动面向对象思想和lseek的实现【转】

    本文转自自:http://blog.chinaunix.net/uid-25014876-id-59418.html linux设备驱动归纳总结(三):3.设备驱动面向对象思想和lseek的实现 一. ...

  7. 转:fopen()函数

    1.2 文件的输入输出函数 键盘.显示器.打印机.磁盘驱动器等逻辑设备, 其输入输出都可以通过文件管理的方法来完成.而在编程时使用最多的要算是磁盘文件, 因此本节主要以磁盘文件为主, 详细介绍Turb ...

  8. fopen()函数

    1.2 文件的输入输出函数 键盘.显示器.打印机.磁盘驱动器等逻辑设备, 其输入输出都能够通过文件管理的方法来完毕.而在编程时使用最多的要算是磁盘文件, 因此本节主要以磁盘文件为主, 具体介绍Turb ...

  9. ioctl、文件操作接口函数以及nand的升级模式的操作过程详解

    概述 内核中驱动文件的操作通常是通过write和read函数进行的,但是很多时候再用户空间进行的操作或许不是内核中公共代码部分提供的功能,此时就需要使用一种个性化的方法进行操作--ioctl系统调用. ...

随机推荐

  1. Mysql5.7修改默认密码

    由于 Mysql5.7的默认密码是随机生成的,所以需要修改成我们自己常用的密码 1.修改 my.ini,在 [mysqld] 小节下添加一行:skip-grant-tables=1 这一行配置让 my ...

  2. Visual Studio 2015 Bowser Link的功能不停的向服务端发送请求

    Visual Studio 2015新建的mvc项目 默认在每个视图上生成一些JavaScript脚本

  3. 教你写一个web远程控制小工具

    惯例先上图 晚上躺床上了,发现忘关电脑了,又不想起来关,来用手机控制电脑多好,百度了下,果然一大把.哈,我自己为什么不自己也实现个呢,任意的自己diy.Just do it. 如果不想看如何实现,那么 ...

  4. WEB前端知识在乱花渐欲迷人眼的当下,如何分清主次和学习优先级呢?

    从正美的吐槽开始,我回了下,说对盲目跟风的大众失去信心了.然后一些同学说我固步自封,另一些同学估计想说倚老卖老啥的.我想说清楚一点,我从 未停止过学习,只是对知识的重要程度和精力分配有自己的观点.具体 ...

  5. LA 3938 动态最大连续和 线段树

    题目链接: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show ...

  6. JavaScript 语句 for

    循环for语句: for(var i =1;i<=5;i++)(初始条件:循环条件:状态改变) { 循环体 } 循环的作用:反复执行某段代码 四要素:初始条件.循环条件.循环体.状态改变 例题1 ...

  7. jquery 事件 多次绑定,多次触发,怎么清除历史绑定事件

    Jquery在处理事件的时候有时候会遇到预想不到的结果 如下 <a id="link_foo">Foo</a> <script type=" ...

  8. php 注入

    SELECT * FROM `users` WHERE name = 'a\'b\'d' LIMIT 0 , 30 这个是有结果的,运行正确的,和一般想的不一样,单引号里面可以套单引号,只要里面的单引 ...

  9. 基于SimHash的微博去重

    一.需求:对微博数据进行去重,数据量比较小,几十万条左右. 二.解决方案 1.采用SimHash的指纹信息去重方法. 三.实现方案 1.对每一条微博使用tf-idf与特征词 2.使用每条微博的特征词, ...

  10. 场景类(CCSence)

    场景与流程控制 在图2-1中,每一个节点中显示的内容相对不变.通常,我们把这些内容相对不变的游戏元素集合称作场景(scene),把游戏在场景之间切换的过程叫做流程控制(flow control). 在 ...