APUE---chap3文件I/O---3.2~3.8(open/close/read/write/lseek)

  • 3.2文件描述符

文件描述符一般用fd(file descriptor)表示,是一个非负整数。

1 一般是从3开始的,因为一个程序运行,会默认自动的打开3个fd,分别是0(stdin) 1(stdout)以及 2 (stderr) 
2 文件描述符的范围是0~OPEN_MAX-1,而因为程序默认打开3个流,所以可打开的流个数为OPEN_MAX - 3 , 可通过命令 ulimits -a 的open files查看

3.这个int fd 代表的是数组下标,  这个数组是程序打开的所有stream的记录。

4.每个文件的使用情况会有一个使用计数,防止不同的地方打开了同一个文件导致一个close()就关了所有的文件。

  • 3.3 函数open

函数定义:调用open 创建或打开一个文件,函数open() 通过变参实现类似重载的效果(类似于printf,参数个数是不确定的)

  flag参数:必须有以下三个参数(其他参数可通过或操作使用)

  • O_CREAT:若文件不存在则创建文件(无则创建)
  • O_TRUNC:若文件只读只写成功打开,长度截断为0,清空文件(有则清空)

 其余参数:用到的时候查书,补充。

  • 3.5 函数close

函数定义:传入的是open()的返回值fd, 若close出错会返回-1

  • 3.6 函数lseek

定义:为一个打开的文件设置“当前文件偏移量”,感觉象是看一张报纸,决定眼睛盯着哪一个字。不过再文件中称之为偏移量。

..

  • 3.7 函数 read

定义

 ..

  • 3.8 函数write

定义

若写出错,返回值为-1,并且会设置errno, 可能的出错值再man 2 write的ERRORS中可看到。 

  • 通过read/write实现两个文件之间的拷贝的 DEMO
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>

#define BUFSIZE 1024

int main(int argc, char **argv) {
    if (argc < 3) {
        fprintf(stderr, "Usage\n");
    }

    // 1.打开两个文件
    int sfd = open(argv[1], O_RDONLY);
    if (sfd < 0) {
        perror("open 1");
        exit(1);
    }
    int dfd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0600);
    if (dfd < 0) {
        close(sfd);  //避免内存泄漏
        perror("open 2");
        exit(1);
    }

    // 2. 读sfd的内容到dfd的内容
    char buf[BUFSIZE];
    while (1) {
        int len = read(sfd, buf, BUFSIZE);
        if (len < 0) {  //读取出错
            perror("read");
            break;
        } else if (len == 0) {  //读取完成
            break;
        }

        int ret = write(dfd, buf, len);
        if (ret < 0) {
            perror("write");
            break;
        }
    }

    // 3. 关闭两个文件
    close(dfd);
    close(sfd);

    exit(0);
}

  • 文件io与标准io区别 
  • 例子

比如:传达室大爷送信到邮局:有两种办法:

1.收一封信,去一次邮局。(文件I/O)

2.收到20封信,去一次邮局。(标准I/O操作,有缓冲)如果收到第6封加急的信件,则立刻去邮局。(fflush()刷新)

  • 区别

标准I/O:具有缓冲的机制,可大大的提高系统的效率。若有紧急需要刷新则可用fflush(),所以吞吐量大。响应速度慢。

文件I/O:无缓冲,是一次实打实的动作。响应速度快,吞吐量小。

  • 面试

问如何让程序变快?反应速度快用文件I/O。吞吐量大用标准I/O。

  • 不可混用 标准,文件I/O

因为标准I/O有缓冲,并不会真正的写到文件里面去。

比如下面的例子,会先输出文件I/O的动作,最后调用标准I/O的动作

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    putchar('a');      // 标准I/O
    write(1, "b", 1);  // 系统调用(文件I/O)

    putchar('a');
    write(1, "b", 1);

    putchar('a');
    write(1, "b", 1);

    exit(0);
}

// 输出结果:  bbbaaa
  • 通过strace ./a.out  即可看到系统调用(文件I/O的调用顺序) 
  • 转换

fileno() // 将标准I/O操作转换为文件I/O操作

fdopen() //将文件I/O转换为标准I/O使用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值