Linux系统编程 46 -lseek函数

学习笔记

lseek函数

文件偏移
以前有接触到fseek 库函数,lseek和它有点类似。

#include <sys/types.h>
#include <unistd.h>

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

第一个参数:文件描述符
第二个参数:偏移量 正负值, 往前往后
第三个参数:设置偏移的起始位置 whence: 从何处,从哪里的意思
三个值:
SEEK_SET :文件的起始位置
SEEK_CUR :文件的当前位置
SEEK_END :文件的末尾位置

返回值:
off_t:一定是与起始位置开始向后的偏移量

错误的时候,返回值为-1,并且设置errno (#include <errno.h>)
注意:文件的读和写使用相同的偏移量。

查看程序:

注意strlen长度不包含'\0'。

$cat lseek.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>

int main(void)
{
    int fd,n;
    char msg[] = "It's a test for lseek\n";
    char ch;

    fd = open("lseek.txt",O_RDWR|O_CREAT,0664);

    if(-1 == fd )
    {
        perror("open lseek.txt error!");
        exit(1);
    }

    write(fd,msg,strlen(msg));
    //lseek(fd,0,SEEK_SET);

    while(( n = read(fd,&ch,1)))
    {
        if( -1 == n)
        {
            perror("read error");
            exit(1);
        }
        write(STDOUT_FILENO,&ch,n);
    }

    close(fd);
    return 0;

}


read 返回值为0的时候,就是文件末尾了。

$./lseek
$ll
total 40
drwxrwxr-x 2 ubuntu ubuntu  4096 12月 22 23:10 ./
drwxrwxr-x 7 ubuntu ubuntu  4096 12月 22 22:58 ../
-rwxrwxr-x 1 ubuntu ubuntu 19800 12月 22 23:10 lseek*
-rw-rw-r-- 1 ubuntu ubuntu   495 12月 22 23:09 lseek.c
-rw-rw-r-- 1 ubuntu ubuntu    22 12月 22 23:10 lseek.txt
-rwxr--r-- 1 ubuntu ubuntu   178 12月 22 22:58 makefile*
$cat lseek.txt
It's a test for lseek


将下面的//去除
//lseek(fd,0,SEEK_SET);


执行的结果不一样,终端也会输出内容。

$vim lseek.c
$make
gcc  lseek.c -o lseek -Wall -g
$./lseek
It's a test for lseek

结论:文件的读和写使用相同的偏移量!!!

应用的场景:
1.文件的读和写使用相同的偏移位置
2.使用lseek取获取文件大小
3.使用lseek取拓展文件大小,要想文件真正的拓展,必需引起IO操作。


通过lseek 去获取文件大小,是一个野路子
正规方式后面再介绍。

使用lseek获取文件的大小很常见。我们就从众吧。

方式:lseek(fd,0,SEEK_END);

查看下面代码:

$cat lseek_test.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
int main(int argc, char* argv[])
{
    int fd;
    int length;

    fd = open(argv[1],O_RDWR);
    if(-1 == fd)
    {
        perror("open error!");
        exit(1);
    }
    length = lseek(fd,0,SEEK_END);
    printf("file size: %d\n",length);
    
    close(fd);
    return 0;
}
$ll
total 64
drwxrwxr-x 2 ubuntu ubuntu  4096 12月 22 23:32 ./
drwxrwxr-x 7 ubuntu ubuntu  4096 12月 22 22:58 ../
-rwxrwxr-x 1 ubuntu ubuntu 19848 12月 22 23:20 lseek*
-rw-rw-r-- 1 ubuntu ubuntu   496 12月 22 23:20 lseek.c
-rwxrwxr-x 1 ubuntu ubuntu 19808 12月 22 23:32 lseek_test*
-rw-rw-r-- 1 ubuntu ubuntu   336 12月 22 23:32 lseek_test.c
-rw-rw-r-- 1 ubuntu ubuntu    22 12月 22 23:20 lseek.txt
-rwxr--r-- 1 ubuntu ubuntu   178 12月 22 22:58 makefile*
$./lseek_test ./lseek.c
file size: 496


都是496。

添加一个f.c 

$./lseek_test  ./f.c
file size: 440

如何扩展到500.拓展文件大小的程序:

$cat lseek_test.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
int main(int argc, char* argv[])
{
    int fd;
    int length;

    fd = open(argv[1],O_RDWR);
    if(-1 == fd)
    {
        perror("open error!");
        exit(1);
    }
    length = lseek(fd,60,SEEK_END);
    printf("file size: %d\n",length);
    close(fd);
    return 0;
}
$make clean
rm -rf ./lseek_test ./f ./lseek  a.out 
$make lseek_test
gcc  lseek_test.c -o lseek_test -Wall -g
$ll
total 5520
drwxrwxr-x 2 ubuntu ubuntu    4096 12月 22 23:50 ./
drwxrwxr-x 7 ubuntu ubuntu    4096 12月 22 22:58 ../
-rwxr--r-- 1 ubuntu ubuntu 5600268 12月 18 17:52 dict.txt.txt*
-rwxr--r-- 1 ubuntu ubuntu     440 12月 22 23:41 f.c*
-rw-rw-r-- 1 ubuntu ubuntu     496 12月 22 23:20 lseek.c
-rwxrwxr-x 1 ubuntu ubuntu   19864 12月 22 23:50 lseek_test*
-rw-rw-r-- 1 ubuntu ubuntu     351 12月 22 23:48 lseek_test.c
-rw-rw-r-- 1 ubuntu ubuntu      22 12月 22 23:20 lseek.txt
-rwxr--r-- 1 ubuntu ubuntu     178 12月 22 22:58 makefile*
$./lseek_test f.c
file size: 500
$ls -l f.c
-rwxr--r-- 1 ubuntu ubuntu 440 12月 22 23:41 f.c

发现有趣的现象。
原因:没有进行IO操作。


修改程序:

$cat lseek_test.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
int main(int argc, char* argv[])
{
    int fd;
    int length;

    fd = open(argv[1],O_RDWR);
    if(-1 == fd)
    {
        perror("open error!");
        exit(1);
    }
    length = lseek(fd,59,SEEK_END);
    printf("file size: %d\n",length);
    write(fd,"a",1);
    close(fd);
    return 0;
}
$make lseek_test
gcc  lseek_test.c -o lseek_test -Wall -g
$./lseek_test ./f.c
file size: 499
$ll
total 5520
drwxrwxr-x 2 ubuntu ubuntu    4096 12月 22 23:57 ./
drwxrwxr-x 7 ubuntu ubuntu    4096 12月 22 22:58 ../
-rwxr--r-- 1 ubuntu ubuntu 5600268 12月 18 17:52 dict.txt.txt*
-rwxr--r-- 1 ubuntu ubuntu     500 12月 22 23:57 f.c*
-rw-rw-r-- 1 ubuntu ubuntu     496 12月 22 23:20 lseek.c
-rwxrwxr-x 1 ubuntu ubuntu   19904 12月 22 23:57 lseek_test*
-rw-rw-r-- 1 ubuntu ubuntu     369 12月 22 23:57 lseek_test.c
-rw-rw-r-- 1 ubuntu ubuntu      22 12月 22 23:20 lseek.txt
-rwxr--r-- 1 ubuntu ubuntu     178 12月 22 22:58 makefile*


filesize为499(因为最后写的a,没有算进去)
ll查看为500.

查看f.c文件


我们将2(没有扩展之前的最后一个字2)和字母a之间的内容一堆^@称为文件空洞,二进制形态为\0.


od -tcx filename 查看文件的16进制表示形式
od -tcd filename 查看文件的10机制表示形式

下面的内容还是有点迷糊。

$od -tcd f.c
0000000   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1
              825307441       825307441       825307441       825307441
*
0000660   1   1   1   1   1   1   1   2  \0  \0  \0  \0  \0  \0  \0  \0
              825307441       842084657               0               0
0000700  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
                      0               0               0               0
*
0000760  \0  \0  \0   a
             1627389952
0000764


truncate函数也可以用来扩展函数的大小

#include <unistd.h>
#include <sys/types.h>

int truncate(const char *path, off_t length);
第一个参数:文件路径,文件必须存在
第二个参数:文件长度

返回:
成功是0
失败是1
int ftruncate(int fd, off_t length);


程序:

$cat trunc.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>

int main(int argc, char *argv[])
{
//open/lseek(fd,249,SEEK_END);/write(fd,"\0",1);//zheyangzi jiudedao 250
    int ret = truncate("./dict.cp",250);
    printf("ret= %d\n",ret);
    return 0;
}


  

$make trunc
gcc  trunc.c -o trunc -Wall -g
$./trunc
ret= -1
$touch dict.cp
$ls -l dict.cp
-rw-rw-r-- 1 ubuntu ubuntu 0 12月 23 00:19 dict.cp
$./trunc
ret= 0
$ll dict.cp
-rw-rw-r-- 1 ubuntu ubuntu 250 12月 23 00:19 dict.cp

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值