文件I/O(不带缓冲)之lseek函数
每个打开的文件都有一个与其相关联的“当前文件偏移量”(current file offset)。它通常是一个非负整数,用以度量从文件开始处计算的字节数。通常,读、写操作都从当前文件偏移量处开始,并使偏移量增加所读写的字节数。按系统默认情况,当打开一个文件时,除非指定O_APPEND选项,否则该偏移量被设置为0。
可以调用lseek显示地为一个打开的文件设置其偏移量:
#include <unistd.h>
off_t lseek( int filedes, off_t offset, int whence );
返回值:若成功则返回新的文件偏移量,若出错则返回-1。
对参数offset的解释与参数whence的值有关。(注意:当前文件偏移量和参数offset是完全不同的概念。)
若whence是SEEK_SET,则将该文件的偏移量设置为距文件开始处offset个字节。
若whence是SEEK_CUR,则将该文件的偏移量设置为其当前位置加offset,offset可为正或负。
若whence是SEEK_END,则将新文件的偏移量设置为文件长度加上offset,offset可为正或负。
若lseek成功执行,则返回新的文件偏移量,为此可以用下列方式确定打开文件的当前偏移量:
off_t currpos;
currpos = lseek( fd, , SEEK_CUR );
这种方法也可用来确定所涉及的文件是否可以设置偏移量。如果文件描述符引用的是一个管道、FIFO或网络套接字,则lseek返回-1,并将errno设置为ESPIPE。
三个符号常量SEEK_SET、SEEK_CUR和SEEK_END是由系统V引入的。在系统V之前,whence被指定为0(绝对偏移量)、1(相对于当前位置的偏移量)或2(相对于文件尾端的偏移量)。现在的很多软件仍然把这些数字直接写在代码里。
lseek中的字符l表示长整型。在引入off_t数据类型之前,offset参数和返回值是长整型。lseek是由V7引入的,当时C语言中增加的长整型(在V6中,用函数seek和tell提供类似的功能)。
程序清单3-1 测试能否对标准输入设置偏移量
[root@localhost apue]# cat prog3-.c
#include "apue.h" int
main(void)
{
if(lseek(STDIN_FILENO, , SEEK_CUR) == -)
printf("cannot seek\n");
else
printf("seek ok\n");
exit();
}
调用此程序,可得:
[root@localhost apue]# ./prog3- < /etc/motd
seek ok
[root@localhost apue]# ./prog3- < /etc/issue
seek ok
关于/etc/motd和/etc/issue的问题可参考:http://itchen.blog.51cto.com/343363/206679
通常,文件的当前偏移量应当是一个非负整数,但是,某些设备也可能允许负的偏移量。但对于普通文件,则其偏移量必须是非负值。因为偏移量可能是负值,所以在比较lseek的返回值时应当谨慎,不要测试它是否小于0,而要测试它是否等于-1。
在Intel x86处理器上运行的FreeBSD上的/dev/kmem设备支持负的偏移量。
因为偏移量(off_t)是带符号数据类型,所以文件最大长度会减少一半。例如,若off_t是32位整型,则文件最大长度是2^31-1个字节。
lseek仅将当前的文件偏移量记录在内核中,它并不引起任何I/O操作。然后,该偏移量用于下一个读或写操作。
文件偏移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写将加长该文件,并在文件中构成一个空洞,这一点是允许的。位于文件中但没有写过的字节都被读为0。
文件中的空洞并不要求在磁盘上占用存储区。具体处理方式与文件系统的实现有关,当定位到超出文件尾端之后写时,对于新写的数据需要分配磁盘块,但是对于原文件尾端和新开始写位置之间的部分则不需要分配磁盘块。
程序清单3-2 创建一个具有空洞的文件
[root@localhost apue]# cat prog3-.c
#include "apue.h"
#include <fcntl.h> char buf1[] = "abcdefghij";
char buf2[] = "ABCDEFGHIJ"; int
main(void)
{
int fd;
if((fd = creat("file.hole", FILE_MODE)) < )
err_sys("creat error");
if(write(fd, buf1, ) != )
err_sys("buf1 write error");
/* offset now = 10 */ if(lseek(fd, , SEEK_SET) == -)
err_sys("lseek error");
/* offset now = 16384 */ if(write(fd, buf2, ) != )
err_sys("buf2 write error");
/*offset now = 16394 */ exit();
}
运行该程序得到:
[root@localhost apue]# ./prog3-
[root@localhost apue]# ls -l file.hole
-rw-r--r-- root root - : file.hole
[root@localhost apue]# od -c file.hole
a b c d e f g h i j \ \ \ \ \ \
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \
*
A B C D E F G H I J
使用od(1)命令观察该文件的实际内容。命令中的-c标志表示以字符方式打印文件内容。从中可以看到,文件中间的未写字节都被读成为0。每一行的开始的一个7位数是以八进制形式表示的字节偏移量。
因为lseek使用的偏移量是用off_t类型表示的,所以允许具体实现根据各自特定的平台自行选择大小合适的数据类型。现今大多数平台提供两组接口以处理文件偏移量:一组使用32位文件偏移量,另一组则使用64位文件偏移量。
注意:尽管可以支持64位文件偏移量,但是否能创建一个大于2GB(2^31-1个字节)的文件则依赖于底层文件系统的类型。
本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/。
文件I/O(不带缓冲)之lseek函数的更多相关文章
- 第十三篇:带缓冲的IO( 标准IO库 )
前言 在之前,学习了 read write 这样的不带缓冲IO函数. 而本文将讲解标准IO库中,带缓冲的IO函数. 为什么要有带缓冲IO函数 标准库提供的带缓冲IO函数是为了减少 read 和 wri ...
- 带缓冲的IO( 标准IO库 )
前言 在之前,学习了 read write 这样的不带缓冲IO函数.而本文将讲解标准IO库中,带缓冲的IO函数. 为什么要有带缓冲IO函数 标准库提供的带缓冲IO函数是为了减少 read 和 writ ...
- 文件I/O(不带缓冲)之原子操作
一.添写至一个文件 考虑一个进程,它要将数据添加到一个文件尾端.早期的UNIX系统并不支持open的O_APPEND选项,所以程序被编写成下列形式: ) < ) /* position to E ...
- 文件I/O(不带缓冲)概述
一.引言 UNIX系统中大多数文件I/O只需用到5个函数:open.read.write.lseek以及close.这些函数经常被称为不带缓冲的I/O(unbuffered I/O).术语不带缓冲指的 ...
- UNIX环境编程学习笔记(2)——文件I/O之不带缓冲的 I/O
lienhua342014-08-25 1 文件描述符 对于内核而言,所有打开的文件都通过文件描述符引用.文件描述符是一个非负整数.当打开一个现有文件或创建一个新文件时,内核向进程返回一个文件描述符. ...
- 文件I/O(不带缓冲)之文件共享
UNIX系统支持在不同进程间共享打开的文件. 内核使用三种数据结构表示打开的文件,它们之间的关系决定了在文件共享方面一个进程对另一个进程可能产生的影响. (1)每个进程在进程表中都有一个记录项,记录项 ...
- 带缓冲的IO和不带缓冲的IO
文件描述符: 文件描述符是一个小的非负整数,是内核用来标识特定进程正在访问的文件 标准输入/输出/出错: shell为每个程序打开了三个文件描述符,STDIN_FILEON,STDOUT_FILEON ...
- Unix文件 I/O(不带缓冲区的)上
简介 Unix系统大多数文件i/o只需要:open.read.write.lseek.close这几个函数.但是某些时候我们也需要fcntl.ioctl.sync等函数配合使用.这些函数都是不带缓冲区 ...
- 带缓冲I/O和不带缓冲I/O的区别与联系
转自:http://blog.csdn.net/lmh12506/article/details/6803847 首先要明白不带缓冲的概念:所谓不带缓冲,并不是指内核不提供缓冲,而是只单纯的系统调用, ...
- 【UNIX环境高级编程】文件 IO 操作 一 ( open | close | creat | lseek | write | read )
博客地址 : http://blog.csdn.net/shulianghan/article/details/46980271 一. 文件打开关闭操作相关函数介绍 1. open 函数 (1) op ...
随机推荐
- LeetCode Product of Array Except Self (除自身外序列之积)
题意:给一个序列nums,要求返回一个序列ans,两序列元素个数相同,ans第i个元素就是除了nums[i]之外所有的数相乘之积. 思路:时间O(n),额外空间O(0). 第一次扫一遍,处理nums[ ...
- C#实现无物理边距真正可打印区域的绘图\打印程序开发
经常在开发实际的应用程序中,需要用到图形绘制和打印程序.如何实现完整的精确打印和绘图是需要注意许多细节地方的.最近在遇到打印问题的时候,仔细研究一阵,总结这篇博文,写得有点杂乱,看文要还请费点神. 基 ...
- Win7下的DragEnter、DragDrop事件不触发的解决方案
Win7与原来的XP和Win2003相比,安全控制方面更严格.比如,当我们以administrator登陆XP或Win2003时,运行所有的程序即是以管理员的身份启动的.但当以administrato ...
- Delphi 打印
procedure TForm1.PrinterSetupExecute(Sender: TObject);begin PrinterSetupDialog1.Execute;end; procedu ...
- java.lang.NoClassDefFoundError: javax/transaction/Synchronization (jUnit测试报错)
测试hibernate 报错原因项目缺少包 在 hibernate 解压目录下找到 jta.jar 文件 往项目中添加该 jar 包,即可解决 添加方法:[右击项目]--> ...
- 在 MacOS 上编译链接 OpenGL 程序
几个星期以前开始折腾在我的MBA上写 OpenGL 小程序.我不太熟悉MacOS上的开发工具比如XCode,所以一开始的想法就是用vim来写程序,然后手工编译链接.网上查了一下,MacOS上的Open ...
- cocos2d-x 2.x版本中,场景切换各方法调用顺序
假设从A场景切换到B场景,调用各场景方法的顺序为: 如果没有切换效果(transition),则先调用B的init(),再调用A的onExitTransitionStart(),接着调用A的onExi ...
- Jquery 操作xml 文档的方法
需求: 页面上有两个下拉框,显示游戏大区 和游戏服务器,当游戏大区改变时,游戏服务器也跟着改变 界面部分html代码 <tr class="tkSigUser"> &l ...
- STM32 串口功能 库函数 详解和DMA 串口高级运用(转载)
数据传输时要从支持那些相关的标准?传输的速度?什么时候开始?什么时候结束?传输的内容?怎样防止通信出错?数据量大的时候怎么弄?硬件怎么连接出发,当然对于stm32还要熟悉库函数的功能 具起来rs232 ...
- python包管理工具
pip 是一个安装和管理 Python 包的工具 , 是 easy_install 的一个替换品.本文将详细说明 安装 pip 的方法和 使用 pip 的一些基本操作如安装.更新和卸载 python ...