详解Linux中文件IO之系统IO

目录

1、文件系统

1.1“裸奔”层次:不带操作系统的编程

1.2带“OS”的编程

1.3Linux文件系统         

1.4进程文件表项

2、系统IO

        2.1Linux系统IO应用

                2.1.1umask

                2.1.2获取进程(程序)的当前工作路径

                2.1.3改变进程的工作路径

                2.1.4文件截短

                2.1.5删除文件

                2.1.6文件属性的获取

        2.2文件的操作步骤

                2.2.1打开文件

                2.2.2读文件

                2.2.3写文件

                2.2.4关闭文件

                2.2.5设置偏移量

2.3目录操作

        2.3.1打开目录

        2.3.2操作目录

        2.3.3关闭目录


谢谢帅气美丽且优秀的你看完我的文章还要点赞、收藏加关注

没错,说的就是你,不用再怀疑!!!

希望我的文章内容能对你有帮助,一起努力吧!!!


1、文件系统

1.1“裸奔”层次:不带操作系统的编程

APP 应用层

-----------------

HardWare 硬件层

特点:

  • 简单,粗暴应用层直接操作硬件(寄存器、IO口...)

缺点:

  • 开发应用、要能搞懂原理图
  • 了解硬件的细节
  • 不能同时运行多个任务:单任务运行

1.2带“OS”的编程

APP 应用层

-----------------

OS 操作系统

-----------------

Hardware 硬件层

特点:

  • 开发应用、主要实现应用的逻辑实现
  • 不需要关心底层硬件的实现细节
  • 可以支持多任务运行、并发

缺点:

  • API(application interface) 太多了
  • API的实现(功能)可能不是我们想要的

OS:Operating System 操作系统。是直接运行在“裸机”的最基本的系统软件,任何软件/应用程序都必 须要在操作系统的支持下才能正常运行。

操作系统:

  • windows  x86/xp/win8/win10/win11
  • linux  ubuntu/centos/redhat/kali
  • mac
  • IOS
  • Android
  • 鸿蒙
  • uinx

Linux操作系统下进行开发应用软件,就是调用Linux操作系统为我们提供的系统的API函数接口去操作硬 件。或者是说用Linux提供的服务来完成linux下的一些开发。

1.3Linux文件系统         

在linux下面,一切皆文件。在linux 下面操作任何东西,其实都是通过操作文件来实现的,通过文件的 接口实现。

文件系统

用来存储、组织、管理文件的一套方式、方法、协议以及软件的实现...

文件:

  • 文件属性:inode(编号),inode----> 文件内容...
  • 文件内容:文件的实际存储的内容

文件在Linux下的操作过程:

  • 硬链接(找文件名)---->inode
  • linux内核

// 是用来描述一个文件的物理的inode信息

系统如果识别到了一个文件的存在,就会问他在linux内核里面创建一个struct inode的一个文 件对应的inode。

struct inode{};

/*

        用来描述一个已经打开了的文件信息的。

         文件状态便宜了(类似于文本光标)

         每个打开的文件都会对应一个struct file

        一个文件是可以被多个不同应用打开

*/

struct file{}

操作过程:struct file ---> struct inode ---> 硬件上的inode ---> 文件内容

linux为了屏蔽文件操作的具体实现细节,它会为进程创建一个“进程文件表项"

1.4进程文件表项

每一个应用都会有一个进程文件表项,保存进程打开的文件的sturct file结构体指针,相当于是一个 struct file *的数组(集合),打开一个文件,只需要返回一个下标给我使用就可以了

struct file* [ ]

打开一个文件,文件的struct file指针被分配到0下标,就可以使用0下标在进程文件表项中获取文件的 struct file指针使用了。

open 打开一个文件

返回值就是打开的文件在进程文件表项中的下标


linux提供系统操作函数:open、write、read、close...以上这些函数都是称为:“系统IO”

系统IO:操作系统所提供的对于文件的输入输出的函数接口

2、系统IO

        2.1Linux系统IO应用

                2.1.1umask

umask:用来设置一个文件的创建的掩码(掩盖部分功能)的。

mask掩码中为1的bit位,在文件创建的时候,不能指定这个bit位所对应的权限

0111 0111 0111 ---> 777 ---> rwx rwx rwx 权限全部没有

通过open创建一个文件的时候如果指定了文件的权限:0777,但是umask值为:0022的时候

实际文件被创建之后的权限为:0777 & ~umask

                                                   0777 & ~ 0022

                                                   0777 & 0755、

                                                   0755

#include <sys/types.h>
#include <sys/stat.h>
#include <iostream>

int main()
{
    // 掩码值
    int mask = 0222;

    int old_mask = umask(mask);

    std::cout << old_mask << std::endl;

    return 0;
}

               每一个进程都会自己的工作(目录)路径,指定文件名要么是绝对路径要么是相对路径,相对路径其实 就是相对于当前程序的工作路径而言。

                2.1.2获取进程(程序)的当前工作路径

获取进程当前的工作目录(路径)的绝对路径

/*
    获取进程的当前工作路径的API
*/

#include <iostream>
#include <unistd.h>

int main()
{
    // 1种 第一种一般不使用
    char wd_array[200];
    if(NULL == getwd(wd_array))
        perror("第一种获取错误");

    // 2种
    char cwd_array[200];
    if(getcwd(cwd_array,200) == NULL)
        perror("第二种获取错误");

    // 3种
    char *current_dir = get_current_dir_name();
    if(current_dir == NULL)
        perror("第二种获取错误");

    std::cout << wd_array << std::endl;
    std::cout << cwd_array << std::endl;
    std::cout << current_dir << std::endl;
     free(current_dir);
    return 0;
}

                2.1.3改变进程的工作路径

改变进程的当前工作路径

/*
    改变进程的当前工作的路径
*/
#include <iostream>
#include <unistd.h>


int main()
{
    char *cut_dir = get_current_dir_name();

    std::cout << "当前工作路径:" << cut_dir << std::endl;

    free(cut_dir);

    std::cout << "修改当前工作路径:" << std::endl;

    chdir("/");

    cut_dir = get_current_dir_name();

    std::cout << "当前工作路径:" << cut_dir << std::endl;

    free(cut_dir);

    return 0;
}

                2.1.4文件截短

用来给一个文件截短内容至指定的长度

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


int main()
{
    // 1
    truncate("./1.txt",5);


    // 2
    int fd = open("./1.txt",O_RDWR);

    ftruncate(fd,10);

    close(fd);
}

注意:

  • length < 源文件长度的时候
    • 源文件中后面的内容看不到了
  • length > 源文件长度的时候
    • undefined,空洞的内容是随机被填充的。一直要扩展到length个字节。

                2.1.5删除文件

删除文件

#include <iostream>
#include <unistd.h>

int main()
{
    unlink("1.txt");

    return 0;
}

删除一个目录

#include <unistd.h>

int main()
{
    rmdir("./1");

    return 0;
}

删除文件/目录

  • remove 删除文件 等价 unlink 删除文件
  • remove 删除目录 等价 rmdir 删除目录

                2.1.6文件属性的获取

获取文件属性

        2.2文件的操作步骤

                2.2.1打开文件

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


int main()
{
    int fd = open("./open1.cpp",O_RDONLY);
    if(fd == -1)
    {
        std::cout << "文件打开失败" << std::endl;
        perror("错误:"); // 打印错误 ,如果文件不存在:No suck file or directory 没有哪个文件或者目录
        return -1;
    }
    std::cout << "文件打开成功" << std::endl;

    close(fd);
    return 0;
}

                2.2.2读文件

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


int main()
{
    int fd = open("./1.txt",O_RDONLY);
    if(fd == -1)
    {
        perror("文件打开失败");
        return -1;
    }

    // 需要有一个空间来存储读取到的数据
    unsigned char data[1000]={0};

    int ret = read(fd,data,500);
    if(ret == -1)
    {
        perror("文件读取失败");
        return -1;
    }

    std::cout << "成功读取到:" << ret << "个字节" << "内容:" << data << std::endl;

    close(fd);
    return 0;
}

                2.2.3写文件

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


int main()
{                                 // 追加内容
    int fd = open("./1.txt",O_RDWR|O_APPEND);
    if(fd == -1)
    {
        perror("文件打开失败");
        return -1;
    }

    // 需要有一个空间来存储读取到的数据
    unsigned char data[1000]={"ABCDEFG"};

    int ret = write(fd,data,strlen((const char*)data));
    if(ret == -1)
    {
        perror("文件写入失败");
        return -1;
    }

    std::cout << "成功写入:" << ret << "个字节" << std::endl;

    close(fd);
    return 0;
}

                2.2.4关闭文件

                2.2.5设置偏移量

有时候咱们想在文件中间某个指定的文件插入内容

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


int main()
{                                 // 追加内容
    int fd = open("./1.txt",O_RDWR|O_APPEND);
    if(fd == -1)
    {
        perror("文件打开失败");
        return -1;
    }

    // 需要有一个空间来存储读取到的数据
    unsigned char data[1000]={"ABCDEFG"};

    int ret = write(fd,data,strlen((const char*)data));
    if(ret == -1)
    {
        perror("文件写入失败");
        return -1;
    }

    std::cout << "成功写入:" << ret << "个字节" << std::endl;

    lseek(fd,9,SEEK_SET);

    char buf[100]={0};

    read(fd,buf,50);

    std::cout << buf << std::endl;

    close(fd);
    return 0;
}

注意:当一个文件被成功打开之后,光标所属位置,在最开始的位置。除非打开的时候使用了 O_APPEND,那么光标就会移动到文件内容的最末尾

注意:当文件没有被关闭,那么进行write/read操作会改变光标位置,光标的偏移会被read/write的 返回值影响。

2.3目录操作

        2.3.1打开目录

        2.3.2操作目录

创建一个目录

读取目录的内容

注意:该结构体成员变量:d_ino、d_name是所有linux系统都支持的。如果想让代码具有更好的可移 植性,该结构体代码中,只能用d_ino、d_name这两个成员变量。

        2.3.3关闭目录

  • 26
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值