zoukankan      html  css  js  c++  java
  • 《UNIX环境高级编程》笔记--read函数,write函数,lseek函数

    1.read函数

    调用read函数从文件去读数据,函数定义如下:
    #include <unistd.h>
    ssize_t read(int filedes, void* buff, size_t nbytes);
    成功则返回实际读取的byte数,如果已经达到文件结尾则返回0,出错则返回-1.

    2.write函数

    调用write函数向打开的文件写入数据,函数定义如下:
    #include <unistd.h>
    ssize_t write(int filedes, void* buff, size_t nbytes);
    成功则返回实际写入的byte数,出错则返回-1.

    3.lseek函数

    每个打开的文件都有一个关联的“当前偏移量”,用于记录从文件到当前当前位置的偏移字节数,lseek函数是设置这个当前偏移量

    的函数,函数的声明如下:
    #include <unistd.h>
    off_t lseek(int filedes, off_t offset, int whence);
    成功则返回新的文件偏移量,失败则返回-1.

    如果whence是SEEK_SET,则文件的偏移量设置为文件开始加上offset个字节。
    如果whence是SEEK_CUR,则文件的偏移量设置为当前偏移量开始加上offset个字节,offset可正可负。
    如果whence是SEEK_END,则文件的偏移量设置为文件长度加上offset个字节,offset可正可负。

    不是每个文件都能够设置偏移量,有些文件如管道,FIFO或socket,无法设置偏移量,可以使用如下函数测试是否可以设置偏移量,
    如果返回-1,则表示不可以。
    off_t currpos;
    currpos = lseek(fd, 0, SEEK_CUR);

    2.实践

    创建一个文件,往文件中写入10个字符,然后再使用lseek定位文件开始加上4个字节的偏移量,然后读取接下来的内容。
    #include <fcntl.h>
    #include <stdio.h>
    
    int main(void){
            int fd,byteNum,result;
            char wbuf[10] = "123456789";
            char rbuf[10];
            if((fd = open("./a.txt", O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IXUSR))<0){
                    perror("open");
                    return -1;
            }
    
            if((byteNum = write(fd, wbuf, 10))<0){
                    perror("write");
                    return -1;
            }
    
            if((result = lseek(fd, 4, SEEK_SET))<0){
                    perror("lseek");
                    return -1;
            }
    
            if((byteNum = read(fd, rbuf, 10)) < 0){
                    perror("read");
                    return -1;
            }
    
            printf("read content:%s
    ",rbuf);
    
            close(fd);
            return 0;
    }
    运行结果:
    read content:56789

    如果将偏移量设置为文件开始加上一个负数,调用lseek就会出错。
    #include <fcntl.h>
    #include <stdio.h>
    
    int main(void){
            int fd,byteNum,result;
            char wbuf[10] = "123456789";
            char rbuf[10];
            if((fd = open("./a.txt", O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IXUSR))<0){
                    perror("open");
                    return -1;
            }
    
            if((byteNum = write(fd, wbuf, 10))<0){
                    perror("write");
                    return -1;
            }
    
            if((result = lseek(fd, -1, SEEK_SET))<0){
                    perror("lseek");
                    return -1;
            }
    
            if((byteNum = read(fd, rbuf, 10)) < 0){
                    perror("read");
                    return -1;
            }
    
            printf("read content:%s
    ",rbuf);
    
            close(fd);
            return 0;
    }
    运行结果:
    lseek: Invalid argument

    是不是offset就一定不能为负数呢,不一定,只要最终的偏移量不小于0就可以了,看下面的例子。
    #include <fcntl.h>
    #include <stdio.h>
    
    int main(void){
            int fd,byteNum,result;
            char wbuf[10] = "123456789";
            char rbuf[10];
            if((fd = open("./a.txt", O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IXUSR))<0){
                    perror("open");
                    return -1;
            }
    
            if((byteNum = write(fd, wbuf, 10))<0){
                    perror("write");
                    return -1;
            }
    
            if((result = lseek(fd, -4, SEEK_CUR))<0){
                    perror("lseek");
                    return -1;
            }
    
            if((byteNum = read(fd, rbuf, 10)) < 0){
                    perror("read");
                    return -1;
            }
    
            printf("read content:%s
    ",rbuf);
    
            close(fd);
            return 0;
    }
    运行结果:
    read content:789

    如果文件偏移量大于文件长度再写入数据,那么生成的文件就会出现空洞。先往文件写入10个字符,再跳过20个字符,再写入10个字符。
    #include <fcntl.h>
    #include <stdio.h>
    
    int main(void){
            int fd,byteNum,result;
            char wbuf[10] = "123456789";
            char rbuf[10];
            if((fd = open("./a.txt", O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR))<0){
                    perror("open");
                    return -1;
            }
    
            if((byteNum = write(fd, wbuf, 10))<0){
                    perror("write");
                    return -1;
            }
    
            if((result = lseek(fd, 40960, SEEK_END))<0){
                    perror("lseek");
                    return -1;
            }
    
            if((byteNum = write(fd, wbuf, 10)) < 0){
                    perror("write");
                    return -1;
            }
    
            close(fd);
            return 0;
    }
    运行结果:
    -rw------- 1 root root 40980 2013-09-09 15:03 a.txt
    使用od命令查看文件内容:
    root@virtual-machine:~# od -c a.txt
     
    0000000   1   2   3   4   5   6   7   8   9              
    0000020                                
    *
    0120000                       1   2   3   4   5   6
    0120020   7   8   9  
    0120024
     
    空洞的内容全部置为0

    查看下文件占用的磁盘大小:
    8 -rw------- 1 root root 40980 2013-09-09 15:41 a.txt
    文件虽然有40980个字节,只占用了8个block,即8K(这边的block不是文件系统的block,而是kernel block,linux中,
    kernel block大小为1K),如果是没有空洞的文件,则占用磁盘大小应该是44K。可见,虽然有空洞,但是实际存储时没
    有占用文件大小的磁盘空间。
  • 相关阅读:
    Linux对文件的权限管理
    在Eclipse中安装TestNG
    JUnit 4 与 TestNG 对比
    postman之HTTP请求
    Fiddler抓包后保存为JMX(jmeter脚本,不限jmeter使用版本)
    JMeter使用之BlazeMeter的安装及初步使用
    Postman的第一个案例演示
    Postman的安装及注意事项
    SVN学习记录
    TestNG中如何执行测试
  • 原文地址:https://www.cnblogs.com/james1207/p/3310586.html
Copyright © 2011-2022 走看看