博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《UNIXLinux程序设计教程》一3.3 设置描述字的文件位置
阅读量:5976 次
发布时间:2019-06-20

本文共 2562 字,大约阅读时间需要 8 分钟。

3.3 设置描述字的文件位置

如同可以用fseek()设置流的文件位置一样,对文件描述字也有类似的操作。函数lseek()可改变一个描述字相连文件的文件位置。

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

参数filedes给出已打开的文件描述字,offset指明相对whence的位移字节数,whence的取值同fseek()一样,只能是符号常数SEEK_SET、SEEK_CUR、SEEK_END之一,分别指明offset是相对文件开始、当前文件位置还是文件尾的偏移。

lseek()的返回值是新文件位置相对文件开始的字节数。例如,如下调用
lseek(fd,0L,SEEK_SET);
lseek(fd,0L,SEEK_END);
分别移动文件位置到文件开始和文件尾。而
n = lseek(fd,0,SEEK_CUR);
读当前文件位置值。描述字没有专门的与ftell()类似的函数。
lseek()只移动文件的当前位置,它并不引起任何I/O动作。文件的新位置可以大于文件的当前大小,在这种情况下,下一次写将扩展该文件。这种情况也称为在文件中生成“空洞”,因为系统并不真正在磁盘为这段区间保留存放空间。如果在数据尾部之后到lseek()设置的偏移量之前这段区域的数据尚未写入,则后继读这段区域将读出0,程序3-2是这种情况的一个示例程序。
例3-2 程序3-2用lseek创建一个含有空洞的文件。
screenshot

运行这个程序可看到如下结果:

% rm file.hole                          /* 保证file.hole是新创建的文件 */% a.out% ls -l file.hole                       /* 查看文件大小 */-rw-r--r--   1 zkj      users         50 Nov  2 15:27 file.hole% od -c file.hole                       /* 查看文件的实际内容 */0000000    a   b   c   d   e   f   g   h   i   j  \0  \0  \0  \0  \0  \00000020   \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \00000040   \0  \0  \0  \0  \0  \0  \0  \0   A   B   C   D   E   F   G   H0000060    I   J

od命令用于查看文件的内容,'-c'选项指定打印内容为字符。其输出内容中左边一列的7个数字为文件位移。我们可以看到30个未写的字节被读出为0,实际上这些字节在未写之前并不占用磁盘空间。

如果放开open调用中对O_APPEND标志的注释之后重新编译0并运行它,则将看到不同的结果:

% rm file.hole% a.out% ls -l file.hole-rw-r--r--   1 zkj      users         20 Nov  2 16:30 file.hole% od -c file.hole0000000    a   b   c   d   e   f   g   h   i   j   A   B   C   D   E   F0000020    G   H   I   J0000024

结果显示紧接在lseek()之后由write()所写的内容并不在lseek()指定的文件位置。出现这种情况的原因是:1)lseek()只改变文件位置而不进行任何实际I/O动作,因而它不会改变inode中的文件大小。也就是说,即使lseek()设置的文件位置超过当前文件尾,它也不会导致当前文件尾发生改变。2)每当对用O_APPEND标志打开的文件执行write()时,当前文件位置将首先移到由inode给出的当前文件大小所指出的位置(回顾3.1节末尾指出的第4点),这强制每一次write()只能在当前文件尾添加数据。这两个原因导致lseek()定位的文件位置在这种情况下不起作用。不论将文件位置移至超过文件尾多远,对于用O_APPEND标志打开的文件,下一次写总是写在当前文件尾,并且当前文件位置将从文件尾起增加所写的字节数。

类似地,对如下调用

lseek(fd, 40, SEEK_END);write(fd, buf2, 10);

write()写入的10个字节将紧接在当前文件尾之后,而不是在当前文件尾第40个字节之后(参见3.1节末尾提到的第5点)。

当同一个文件有多个打开的描述字时(被多次打开或由dup()重复),由不同open()得到的文件描述字具有独立的文件位置。lseek()只作用于指定的描述字而不会对另外的描述字造成影响,例如:

{   int d1,d2;   char buf[4];   d1 = open("foo",O_RDONLY);   d2 = open("foo",O_RDONLY);   lseek(dl,1024,SEEK_SET);   read(d2,buf,4);}

read()将读文件foo的前4个字符。但是,由dup()重复而得的描述字与原描述字共享一个公共的文件位置,改变两个重复描述字中一个的文件位置,包括读或写数据,同时也改变了另一个描述字的文件位置。例如:

{    int d1,d2;    char buf1[80],buf2[80];    d1 = open("foo",O_RDONLY);    d2 = dup(d1);    lseek(d1,1024,SEEK_SET);    read(d1,buf1,4);    read(d2,buf2,4);}

第一个read()将从foo的第1024个字符处开始读4个字节,第二个read()则从第1028个字符处再读4个字节。

转载地址:http://elpox.baihongyu.com/

你可能感兴趣的文章
Java小细节
查看>>
poj - 1860 Currency Exchange
查看>>
洛谷 P2486 BZOJ 2243 [SDOI2011]染色
查看>>
数值积分中的辛普森方法及其误差估计
查看>>
Web service (一) 原理和项目开发实战
查看>>
跑带宽度多少合适_跑步机选购跑带要多宽,你的身体早就告诉你了
查看>>
Javascript异步数据的同步处理方法
查看>>
iis6 zencart1.39 伪静态规则
查看>>
SQL Server代理(3/12):代理警报和操作员
查看>>
Linux备份ifcfg-eth0文件导致的网络故障问题
查看>>
2018年尾总结——稳中成长
查看>>
通过jsp请求Servlet来操作HBASE
查看>>
Shell编程基础
查看>>
Shell之Sed常用用法
查看>>
Centos下基于Hadoop安装Spark(分布式)
查看>>
mysql开启binlog
查看>>
设置Eclipse编码方式
查看>>
分布式系统唯一ID生成方案汇总【转】
查看>>
并查集hdu1232
查看>>
Mysql 监视工具
查看>>