26_文件IO

文件IO

文件描述符

​ 对于文件 IO 来说, 一切都是围绕文件操作符来进行的。 在 Linux 系统中, 所有打开的文件都有一个对应的文件描述符。

​ 文件描述符的本质是一个非负整数, 当我们打开一个文件时, 系统会给我们分配一个文件描述符。

​ 当我们对一个文件做读写操作的时候, 我们使用 open 函数返回的这个文件描述符会标识该文件,并将其作为参数传递给 read 或者 write 函数。 在 posix.1 应用程序里面, 文件描述符 0,1,2 分别对应着标准输入, 标准输出, 标准错误。

open函数

image-20240402155257092

参数 flags 可选标志:

image-20240402155312905

当参数flags=O_CREAT时,可以加上第三个参数mode表面权限

文件的权限

​ 文件的访问权限我们可以使用数字来表示:
​ 可执行 x ->1
​ 可写 w ->2
​ 可读 r ->4
​ 例:
​ 如果我们要表示可读可写,就是上述值的和,可读可写->6

代码

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

int main(int argc, char const *argv[])
{

    int fd;                                   // 文件描述符
    fd = open("a.c", O_CREAT | O_RDWR, 0666); // 不存在就创建 可读可写模式 读写权限
    if (fd < 0)
    {
        printf("open is error\n");
    }
    printf("fd is %d\n", fd);

    return 0;
}

运行结果

image-20240402162341198image-20240402162424215

发现问题: a.c的文件权限不是0666

open函数创建文件时的权限是我们设置的mode&~(umask)

image-20240402162725072

即: 0666&~(0022)

​ 110 110 110 & ~(000 010 010)

​ 110 110 110 & 111 101 101

​ 110 100 100 -> 6 4 4 -> rw - r-- r--

close函数

image-20240402171454047

代码

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

int main(int argc, char const *argv[])
{

    int fd;                                   // 文件描述符
    fd = open("a.c", O_CREAT | O_RDWR, 0666); // 不存在就创建 可读可写模式 读写权限
    if (fd < 0)
    {
        printf("open is error\n");
    }
    printf("fd is %d\n", fd);
    close(fd);
    return 0;
}

read函数

image-20240402172119201

正常读

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

int main(int argc, char const *argv[])
{

    int fd;                                   // 文件描述符
    char buf[32]={0};
    ssize_t ret;
    fd = open("a.c", O_CREAT | O_RDWR, 0666); // 不存在就创建 可读可写模式 读写权限
    if (fd < 0)
    {
        printf("open is error\n");
        return -1;
    }
    printf("fd is %d\n", fd);

    ret = read(fd, buf, sizeof(buf));
    if(ret < 0)
    {
        printf("read is error\n");
        return -2;
    }
    printf("buf is %s\n", buf);
    printf("ret is %ld\n", ret);
    close(fd);
    return 0;
}

运行结果

image-20240402172924047

生成的文件中最后多一个\n,所以一个9个字符

读到结尾再读一次

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

int main(int argc, char const *argv[])
{

    int fd;                                   // 文件描述符
    char buf[32]={0};
    ssize_t ret;
    fd = open("a.c", O_CREAT | O_RDWR, 0666); // 不存在就创建 可读可写模式 读写权限
    if (fd < 0)
    {
        printf("open is error\n");
        return -1;
    }
    // printf("fd is %d\n", fd);

    ret = read(fd, buf, sizeof(buf));
    if(ret < 0)
    {
        printf("read is error\n");
        return -2;
    }
    printf("buf is %s\n", buf);
    printf("ret is %ld\n", ret);

    ret = read(fd, buf, sizeof(buf));
    printf("ret is %ld\n", ret);

    close(fd);
    return 0;
}

运行结果

image-20240402173231443

ret返回0表示已经读到文件末尾

write函数

image-20240402173518217

代码

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

int main(int argc, char const *argv[])
{

    int fd;                                   // 文件描述符
    char *buf="hello\n";
    ssize_t ret;
    
    fd = open("a.c", O_CREAT | O_RDWR, 0666); // 不存在就创建 可读可写模式 读写权限

    if (fd < 0)
    {
        printf("open is error\n");
        return -1;
    }
    // printf("fd is %d\n", fd);
    

   write(fd, buf, sizeof(buf));

    close(fd);
    return 0;
}

运行结果

image-20240403132907496

综合练习

通过命令行操作,把a.c文件里面的内容写到b.c里面。

代码

open.c

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

int main(int argc, char const *argv[])
{
    int fd_src, fd_obj;
    ssize_t ret = 0;
    char buf[32];
    if(argc != 3)
    {
        printf("Usage:%s <src file> <obj file>\n", argv[0]);
        return -1;
    }
    fd_src = open(argv[1], O_RDONLY);
    fd_obj = open(argv[2], O_CREAT|O_WRONLY, 0666);

    while((ret = read(fd_src, buf, sizeof(buf))) != 0)
    {
        write(fd_obj, buf, ret);
    }

    close(fd_src);
    close(fd_obj);

    return 0;
}

运行结果

image-20240403140145389

lseek函数

介绍

​ 所有打开的文件都有一个当前文件偏移量(current file offset) ,以下简称为 cfo。

​ cfo 通常是一个非负整数, 用于表明文件开始处到文件当前位置的字节数。 读写操作通常开始于 cfo, 并且使 cfo 增大, 增量为读写的字节数。 文件被打开时, cfo 会被初始化为0, 除非使用了 O_APPEND 。 使用 lseek 函数可以改变文件的 cfo 。

image-20240403140603056

成功返回当前指针位置

举个例子
 把文件位置指针设置为 100 lseek(fd,100,SEEK_SET);
 把文件位置设置成文件末尾 lseek(fd,0,SEEK_END);
 确定当前的文件位置 lseek(fd,0,

posted @ 2024-04-10 19:55  爱吃冰激凌的黄某某  阅读(3)  评论(0编辑  收藏  举报