linux系统编程之文件与I/O(二):文件的读取写入

来源:互联网 发布:淘宝店铺分享到微信 编辑:程序博客网 时间:2024/05/22 06:28

文件的随机读写

到目前为止的所有文件访问都是顺序访问。这是因为所有的读和写都从当前文件的偏移位置开始,然后文件偏移值自动地增加到刚好超出读或写结束时的位置,使它为下一次访问作好准备。
有个文件偏移这样的机制,在Linux系统中,随机访问就变得很简单,你所需做的只是将当前文件偏移值改变到有关的位置,它将迫使下一次read()或write()发生在这一位置。(除非文件打开时标志有 O_APPEND,在这种情况下,任何write调用仍将发生在文件结束处)

lseek系统调用:

功能说明:通过指定相对于开始位置、当前位置或末尾位置的字节数来重定位,这取决于 lseek() 函数中指定的位置
函数原型:off_t lseek (int  fd,    off_t offset,   int base);

函数参数:

fd:需要设置的文件描述符

offset:偏移量

base:偏移基位置

返回值:返回新的文件偏移值

base 表示搜索的起始位置,有以下几个值:(这些值定义在<unistd.h>)

base 文件位置

SEEK_SET 从文件开始处计算偏移
SEEK_CUR 从当前文件的偏移值计算偏移
SEEK_END 从文件的结束处计算偏移


注意:管道和socket是不能lseek的,否则返回ESPIPE错误(Invalid seek)。


#include<sys/types.h>#include<sys/stat.h>#include<unistd.h>#include<fcntl.h>#include<stdio.h>#include<stdlib.h>#include<errno.h>#include<string.h>#define ERR_EXIT(m) \    do { \        perror(m); \        exit(EXIT_FAILURE); \    } while(0)int main(int argc, char *argv []){int infd;int outfd;infd = open("test", O_RDONLY);if (infd == -1)ERR_EXIT("open src error");if ((outfd = open("test", O_WRONLY | O_CREAT | O_TRUNC, 0664)) == -1)ERR_EXIT("open dest error");char buf[1024];ssize_t nread;while ((nread = read(infd, buf, 1024)) > 0)write(outfd, buf, nread); // 可以调用fsync同步内核缓冲区的数据到磁盘文件// 或者打开文件时标志为O_SYNCclose(infd);close(outfd);/********************************************************************************************/int fd = open("test.txt", O_RDONLY);if (fd == -1)ERR_EXIT("open error");char buf2[1024] = {0};int ret = read(fd, buf2, 5);if (ret == -1)ERR_EXIT("read error");ret = lseek(fd, 0, SEEK_CUR); // 从当前位置偏移0个字节if (ret == -1)ERR_EXIT("lseek");printf("current offset=%d\n", ret);fd = open("hole.txt", O_WRONLY | O_CREAT | O_TRUNC, 0664);if (fd == -1)ERR_EXIT("open error");write(fd, "ABCDE", 5);ret = lseek(fd, 1012 * 1024 * 1024, SEEK_CUR);if (ret == -1)ERR_EXIT("lseek error");write(fd, "hello", 5);/* 中间的空字符不占用磁盘空间,如ls -lh hole.txt 与 du -h hole.txt * 看到的文件大小不一样*/close(fd);return 0;}

程序的前部分实现了拷贝文件的基本功能,后部分示例了lseek的用法,因为有些程序需要输入参数,且讨论程序输出结果也比较繁琐,比如上述关于hole.txt文件的实际大小问题,大家可以自己拷贝程序进行测试,印象也更加深刻。

在struct stat结构体中的文件长度对应st_size字段,而文件使用的块大小对应st_blksize字段,占用块数对应st_blocks字段。 大部分情况下面,st_size和st_blksize*st_blocks应该是很接近的,除非一种情况就是文件空洞。 一般对应于空洞文件来说,st_size可能很大,而实际占用磁盘空间却很少。


0 0
原创粉丝点击