基础IO

基础IO:IO接口的基本认识与使用,文件描述符与重定向,静态库与动态库的生成与使用

函数IO接口: fopen  fwrite  fread  fseek  fclose

系统调用IO接口:

        库函数是对系统调用接口的封装

        接口: open  write  read  lseek  close

        int open(char *pathname , int flag , int mode);

                pathname: 要打开的文件路径名

                flag: 文件的打开方式,打开方式决定了能够对文件进行什么样的操作

                        必选项:O_RDONLY  O_WRONLY  O_RDWR   但是只能选其一,不能同时使用

                        可选项:O_CREAT 文件不存在则创建 

                                       O_TRUNC 截断文件,丢弃原有数据

                                       O_APPEND 追加写

                如 w+(可读可写,文件已经存在则截断内容为0) —— O_RDWR|O_CREAT|O_TRUNC

                mode:当O_CREAT被使用时,就一定要设置第三个参数mode——用于设定被创建文件的访问权限0664

                        0664——特别需要注意,0不能被省略,会涉及到特殊权限位的设置

                        给定的权限不一定是实际得到的权限,实际的文件权限会受到umask的影响

                        实际的权限 = 给定的权限 & (~umask)

                        mode_t umask(mode_t mask);  用于设置调用进程的权限掩码

                返回值:成功返回一个文件描述符(非负整数)作为文件的操作句柄; 

                               失败返回-1

        ssize_t write(int fd, char *buf, size_t len);

                fd: open打开文件时返回的操作句柄——文件描述符

                buf:要写入文件的数据的所在空间首地址

                len:要写入的数据长度(以字节为单位)

                返回值:成功返回实际写入的数据长度:

                              失败返回-1;

        ssize_t read(int fd, char *buf, size_t len);

                fd:open打开文件时返回的文件描述

                buf:一块空间的首地址,用于存放读取到的数据

                len:要读取的数据长度(这个长度不能大于buf空间的大小,避免越界)

                返回值:成功返回实际读取到的数据长度(字节为单位)

                              0表示读取到了文件末尾

                              -1表示失败

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

                fd:文件描述符

                offset:偏移量

                whence:偏移其实位置 SEEK_SET;  SEEK_CUT;  SEEK_END;

                返回值:当前跳转后,读写位置相对于文件其实位置的偏移量(接口有另一种另类的用法,跳转到末尾,通过返回值确定文件大小)

        int close(int fd);

                fd:文件描述

#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#incldue <unistd.h>
#include <sys/stat.h>

int main()
{
    umask(0);//将当前调用进程的文件权限创建掩码设置为0,这样open给定的权限就是实际创建得到的权限
    int fd = open("./tmp.txt", O_CREAT|O_RDWR|O_TRUNC, 0777);//110110100

    if(fd < 0)
    {
        perror("open error");
        return -1;
    }

    char *data = "天黑了";
    ssize_t ret = write(fd, data, strlen(data));
    if (ret < 0)
    {
        perror("write error");
        close(fd);
        return  -1;
    }

    lseek(fd, 0, SEEK_SET);

    char buf[1024] = {0};
    ret = read(fd, buf, 1023);//成功返回实际读到的数据长度,返回0表示到达文件末尾没有读到数            
                              //据,-1表示出错
    if(ret < 0)
    {
        perror("read error");
        close(fd);
       return -1;
    }

    printf("%s", buf);
    close(fd);
    return 0;
}

        因为系统调用接口功能比较单一,在某些特定的场景下用起来比较麻烦,因此做了进一步的操作:库函数是对系统调用接口的封装

        printf将数据写入显示器文件,但是不单单是写入,还包含了数据的格式化(将多个数据按照指定格式组织成为一个字符串再写入)

        库函数fopen, fwrite, fread, fclose都是对系统调用接口open, write, read, close接口的封装

封装的目的是什么?

        FILE *fopen(char *pathname...);  fwrite(char *buf, int size...)     FILE *fp是操作句柄

        int open(char *pathname...);        write(int fd, char *buf,int len)  int fd是操作句柄

fwrite是个库函数,本质上内层肯定要调用系统调用接口write,则需要传入一个文件描述符

注意:封装不仅仅是接口,还有操作句柄,实际上FILE这个结构体中就包含了文件描述符成员

        FILE结构体本身就是对文件描述符的一层封装

        通常说,向文件写入数据,数据并不会立即被写入文件,而是先写入缓冲区,等刷新缓冲区的时候写入文件,对于系统调用接口来说,本质上是没有这个缓冲区的,因此write向显示器写入数据是直接打印的;而printf,fprintf,fwrite是刷新缓冲区的时候才打印

        _exit和exit都是退出进程,区别在于是否刷新缓冲区,其实我们所说的缓冲区,对于系统调用接口来说根本就是不存在,因此系统调用接口_exit退出前就没有刷新缓冲区这么一说,最基础的文件流结构针对文件描述符做的一个改进:添加缓冲区

文件描述符:

        文件描述符:被打开的文件的操作句柄——是一个非负整数

                              文件描述符,本质上是一个数组下标,对应的数组保存的是进程打开的文件的                        描述信息,当操作文件的时候需要传入描述符,其实就是通过描述符这个下标找到                          对应的文件描述信息,进而操作文件

        1. 当我们打开了一个文件,涉及到对对应设备的操作

        2. 用一个结构将这个设备描述起来(磁盘文件,就是要描述操作时哪一块硬盘的多少数据,以及权限)一个进程中可能会打开很多文件,这些描述信息就需要组织起来(本质使用了一个数组)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值