• 7底层文件读写


    低级文件库

      低级文件读写与标准文件读写类似。如fgetc,fputs都是调用read,write。

    文件打开/创建
    #include <fcntl.h> //file control
    int open(const char *filename, int flag, [mode_t mode])
    flag 打开文件的模式
    创建文件时,决定新文件的属性 rwx
    int close(int fd)
    关闭文件

    第二参数:
    打开文件的模式(flag 参数的值)
    读写方式
    O_RDONLY 只读
    O_WRONLY 只写
    O_RDWR 读写
    创建方式
    O_APPEND 追加方式打开
    O_CREAT 文件不存在则创建
    O_EXCL 文件存在则打开失败 (创建新文件时,和 O_CREAT 一起用)
    O_NDELAY 不阻塞返回, 返回0
    O_NONBLOCK 不阻塞返回,读取不到数据返回 -1
    O_NOCTTY 程序不作为控制终端
    O_TRUNC 文件存在则清空文件

    第三参数:
    创建文件的模式
    S_IRUSR + S_IWUSR + S_IXUSR = S_IRWXU = 0700 (八进制)
    S_IRGRP + S_IWGRP + S_IXGRP = S_IRWXG = 0070 (八进制)
    S_IROTH + S_IWOTH + S_IXOTH = S_IRWXO = 0007 (八进制)


    文件处理
    #include<unistd.h>
    unlink(char *filename)
    删除文件,只是使用临时文件时候,可以先删除再使用
    size_t read(int fd, void *buf, size_t size)
    读文件
    size_t write(int fd, void *buf, size_t size)
    写文件
    off_t lseek(int fd, off_t offset, int mode)
    使用方法同 fseek()
    int fsync(int fd)
    刷新缓冲区,类似 fflush()
    int dup(int fd)
    重定向文件描述符 int newFd = dup(STDOUT_FILENO)
    newFd 指向 stdout
    int dup2(int fd1, int fd2)
    重定向文件描述符 dup2(newFd, STDOUT_FILENO)
    stdout 指向 newFd

    例子:
    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>

    void test_open()
    {
    int fd;
    fd=open("1.txt",O_RDONLY,0700);
    if(fd<0)
    {
    perror("fail to open");
    return ;
    }
    char buf[1024];
    read(fd,buf,sizeof(buf)); //读取1.txt文件内容
    close(fd);
    printf("buf:%s",buf); //输出文件内容

    read(STDIN_FILENO,buf,strlen(buf)); //读取stdin,等同于scanf()
    printf("input:%s ",buf);

    write(STDOUT_FILENO,buf,strlen(buf));//写入stdout,等同于printf()
    printf("input:%s ",buf);
    }

    void test_dup()
    {
    int fd;
    char buf[1024]="hello world ";

    //此处STDOUT_FILENO与//STDIN_FILENO功能一样
    fd=dup(STDOUT_FILENO);
    write(fd,buf,strlen(buf)); //等同于printf()

    char temp[1024];
    read(fd,temp,sizeof(temp)); //等同于scanf()
    printf("temp:%s",temp);
    }

    void main()
    {
    //test_open();
    test_dup();
    }

    区别;
    这是 fopen版本 的标准输出,错误输出和标准输入, 变量类型是 FILE*
    stdout
    stderr
    stdin


    这是 open 版本的 标准输出,错误输出,和标准输入,变量类型是 int
    STDOUT_FILENO == 1
    STDERR_FILENO == 2
    STDIN_FILENO == 0

    文件控制
    #include<fcntl.h>
    int fcntl(int fd, int cmd)
    int fcntl(int fd, int cmd, int arg);
    int fcntl(int fd, int cmd, struct flock* lock)

    控制命令 cmd
    F_DUPFD
    fcntl(fd, F_DUPFD, 0) 等价于 dup(fd)
    返回大于等于0的最小可用文件描述符
    fcntl(fd1, F_DUPFD, fd2)
    等价于 dup2(fd1, fd2) close(fd2);
    F_GETFD, F_SETFD
    获取设置 FD_CLOEXEC 标志 (执行外部程序 fd 是否关闭, 默认为0,不关闭)
    flag = fcntl(fd, F_GETFD); fcntl(fd , F_SETFD, ~FD_CLOEXEC)
    F_GETFL, F_SETFL
    获取设置文件打开方式:支持设置的有 O_APPEND, O_NONBLOCK,
    F_GETDOWN, F_SETDOWN 获取设置 接受SIGIO,SIGURG 事件信号
    F_GETLK, F_SETLK, F_SETLKW 获取、设置、测试锁

    文件锁
    读锁(共享锁) 写锁 (互斥锁)
    文件可以设置多个读锁,但只能设置一个写锁,读写锁不能同时存在
    stcuct flock
    {
    short l_type //F_RDLCK, F_WRLCK, F_UNLCK (读,写,释放锁)
    short l_whence //锁开始位置 SEEK_SET, SEEK_CUR, SEEK_END
    long l_start //锁偏移量
    long l_len //锁区域大小
    short l_pid //拥有锁的pid
    }
    whence=SEEK_SET, start = len = 0 锁整个文件


    struct flock lock={0, SEEK_SEET, 0,0,0};
    fcntl(fd, F_GETLK, &lock)
    返回值-1表示获取失败
    lock.l_type = F_WRLCK或者F_RDLCK或者F_UNLCK 分别表示锁类型
    fcntl(fd, F_SETLK, &lock)
    lock.l_type = F_WRLCK 或者 F_RDLCK申请锁,失败返回 -1
    fcntl(fd, F_SETLKW, &lock)
    lock.l_type = F_UNLCK 失败返回 -1。

    解析:
    多个进程一起操作某个文件 (需要互斥)
    每个进程,打开文件前,需要检查文件是否被锁定

    进程 A 需要操作文件 某个部分
    --先使用GETLK 查看这个部分是否被锁定了 fcntl(fd, F_GETLK, &lock)
    1:如果被 写锁锁定了 lock.l_type = F_WRLCK
    那么进程 A 不能操作这个文件
    2:如果被 读锁锁定了 lock.l_type = F_RDLCK
    如果进程 A 需要读这个文件,则再次给文件 加上 读锁, 然后开始读取文件
    如果进程 A 需要写这个文件,则等待 (不能写)
    3:如果没有被锁定 lock.l_type = F_UNLCK
    则 A 给文件加上 锁 (读文件就加读锁,写文件就加写锁) fcntl(fd, F_SETLK, &lock)
    --A 使用完成后,如果 A 给文件加锁了,
    需要释放锁 fcntl(fd, F_SETLK, &lock) 【lock.l_type=F_UNLCK】

    目录操作
    #include<unistd.h>
    char * getcwd(char *path, size_t size)
    char * getwd(char *path) //不安全,废弃
    获取当前目录绝对路径
    chdir(char *path) //可以使用相对路径
    设置path为当前工作目录,需要对目录有x权限
    fchdir(int fd)
    设置fd对应的目录为当前工作目录


    #include<sys/stat.h>
    int mkdir(const char *path, mode_t mode)
    创建目录
    int rmdir(char *path)
    删除目录


    读取目录
    #include<dirent.h>
    DIR * opendir(const char *path) //FILE* p =…
    打开目录
    struct dirent *readdir(DIR *pDir) //fread(p, ...)
    读取目录(entity)
    int close(DIR *pDir)
    关闭目录

    void seekdir(DIR *pDir, long locate)
    类似seek()
    void rewinddir(DIR *pDir)
    类似rewind()
    long telldir(DIR *pDir)
    类似ftell()


    struct dirent {
    ino_t d_ino; /* inode number */
    off_t d_off; /* not an offset; see NOTES */
    unsigned short d_reclen; /* length of this record */
    unsigned char d_type; /* type of file; not supported
    by all filesystem types */
    char d_name[256]; /* filename */
    };


    读取文件例子:
    #include <stdio.h>
    #include <dirent.h>
    #include <unistd.h>

    void DirTree(char *szBasePath,int nDeep)
    {
    DIR *pDir;
    int i;
    char *szSubPath;
    struct dirent* pDirent;

    pDir=opendir(szBasePath); //打开目录
    if(pDir==NULL)
    {
    perror("fail open dir");
    return ;
    }
    while(1)
    {
    pDirent=readdir(pDir); //读取目录,获取其属性
    if(pDirent==NULL)
    {
    break;
    }
    //一定要判断,不要后面的递归会出现死循环,不断在本级目录和上级目录
    if(!strcmp(pDirent->d_name,".")||!strcmp(pDirent->d_name,".."))
    {
    continue;
    }
    for(i=0;i!=nDeep;++i)
    {
    printf("| ");
    }
    //目录,递归
    if(pDirent->d_type==DT_DIR)
    {
    printf("|--%s ",pDirent->d_name);
    sprintf(szSubPath,"%s/%s",szBasePath,pDirent->d_name);
    DirTree(szSubPath,nDeep+1);
    }
    //文件
    else
    {
    printf("|--%s ",pDirent->d_name);

    }
    }
    close(pDir);
    }

    void main()
    {
    //char szPath[PATH_MAX];
    //getcwd(szPath,PATH_MAX);
    char *szPath="/home";
    printf("%s ",szPath);
    DirTree(szPath,1);
    }

  • 相关阅读:
    第2章 类模板:2.3 类模板的局部使用
    第2章 类模板:2.2 类模板Stack的使用
    第2章 类模板:2.1 类模板Stack的实现
    第1章 函数模板:1.6 但是,我们不应该…?
    第1章 函数模板:1.5 重载函数模板
    第1章 函数模板:1.4 默认模板参数
    第1章 函数模板:1.3 多模板参数
    第1章 函数模板:1.2 模板参数的推导
    第1章 函数模板:1.1 初识函数模板
    第31课 std::atomic原子变量
  • 原文地址:https://www.cnblogs.com/gd-luojialin/p/9215954.html
Copyright © 2020-2023  润新知