首页 > 其他分享 >文件操作

文件操作

时间:2023-08-09 20:22:43浏览次数:26  
标签:文件 const int char mode 操作 权限

一、一切皆文件
Linux/UNIX操作系统把所有的服务、设备、协议都抽象成文件的形式,提供了一套统一而简单的文件IO的系统调用,简称系统的文件IO
也就是说在UNIX\Linux中任何对象都可以被当做是某种特殊的文件,都可以像访问文件一样,访问这些对象
文件分类:
普通文件 - 包括纯文本文件、二进制文件、各种压缩文件
目录文件 d 必须有读权限才能进入目录
块设备文件 b 保存大块数据的硬件设备,例如磁盘
字符设备文件 c 操作字符相关的设备 例如键盘、鼠标等
socket文件(套接字文件) s 通常用于网络通信
管道文件 p 用于进程间通信
链接文件 l 类似Windows的快捷方式

二、文件相关的系统调用

int open(const char *pathname, int flags);
    功能:打开文件
    pathname:文件的文件
    flags:打开文件的方式
        O_RDONLY    只读
        O_WRONLY    只写
        O_RDWR      读写
        O_APPEND    追加
        O_CREAT     文件不存在则创建
        O_EXCL      配合O_CREAT,如果文件存在则失败
        O_TRUNC     文件如果存在,则清空打开
    返回值:文件描述符,类似于FILE*,代表了一个打开的文件(>=0),负数表示失败
    int open(const char *pathname, int flags, mode_t mode);
    功能:创建文件
    flags:O_CREAT
    mode:
        S_IRWXU  00700 拥有者 读写执行权限
        S_IRUSR  00400        读权限
        S_IWUSR  00200        写权限
        S_IXUSR  00100        执行权限
        S_IRWXG  00070 同组用户 读写执行权限
        S_IRGRP  00040         读
        S_IWGRP  00020          写
        S_IXGRP  00010          执行
        S_IRWXO  00007 其它用户 读写执行权限
        S_IROTH  00004          读
        S_IWOTH  00002          写
        S_IXOTH  00001          执行
        注意:可给宏名 也可以给 权限掩码 (0xxx) 八进制

    int creat(const char *pathname, mode_t mode);
    功能:创建文件
    mode:同上
    练习:测试fopen的各种打开方式与open的flags的对应情况
        strace ./a.out

    ssize_t write(int fd, const void *buf, size_t count);
    功能:把内存中的数据写入的文件中
    fd:文件描述符 open creat的返回值
    buf:待写入的内存的首地址
    count:要写入的字节数
    返回值:成功写入的字节数

    ssize_t read(int fd, void *buf, size_t count);
    功能:从文件中读取数据到内存中
    fd:文件描述符 open creat的返回值
    buf:存储读取出来的数据的内存首地址
    count:要读取的字节数
    返回值:成功读取的字节数

分别使用标准IO和系统IO写入一百万个整数到文件,测试谁的时间更短?为什么?
结论:在同等数据的写入下,使用标准IO要比直接使用系统IO更快
原因:标准IO有缓冲区机制,在执行fwrite写文件时,数据不是直接调用系统IO写入磁盘,而是先存放在内存的缓冲区中,直到缓冲区满后才会调用一次系统IO全部写入到磁盘,因此对系统IO的调用次数、用户态内核态的转换次数都大大降低
而直接使用系统IO是没有缓冲区机制,因此耗时增加
解决:如果给系统IO也加上缓冲区机制,那么它的速度要比标准IO更快

随机读写:
    每个打开的文件都有一个记录读写位置的指针,也称文件位置指针,对文件的读写时该指针会自动往后移动,因此顺序读写时无需操作
    当需要去文件的任意位置进行读写时,才需要调整该指针的位置
    标准IO:
        int fseek(FILE *stream, long offset, int whence);
        返回值:成功0 失败-1
    系统IO:
        off_t lseek(int fd, off_t offset, int whence);
        返回值:成功返回调整后位置指针的位置 失败-1

系统IO中的文本文件的读写:
在系统IO中没有类似fprintf\fscanf函数,因此没有直接对文本文件读写的操作
但是可以通过把数据转换成字符串进行间接的文本文件读写
写文本文件
任意类型数据对象 sprintf 转换成字符串 write写入
读文本文件
按字符串格式读取到内存 sscanf 解析到任意类型数据中

文件描述符:
1、非负整数,代表了一个打开的文件
2、通过系统调用(open\creat)返回,该数值是被内核使用的
3、它在内核中对应一个内核对象,因为内核不能暴露它真实的地址,因此不能直接返回真实的文件地址,而是使用文件描述符来表示
4、内核中有一张记录了所有已打开的文件的二维表,文件描述符就是访问该表每行的下标,文件描述符也称为句柄,就是访问文件的凭证
5、内核中有三个默认长期打开的文件描述符
0 标准输入 宏STDIN_FILENO FILE* stdin
1 标准输出 STDOUT_FILENO stdout
2 标准错误 STDERR_FILENO stderr

文件描述符的重定向:
    int dup(int oldfd);
    功能:复制一个已经打开的文件描述符
    返回值:返回一个当前进程没有使用的最小的文件描述符,该描述符与oldfd对应一个文件
    int dup2(int oldfd, int newfd);
    功能:复制oldfd文件描述符为newfd

文件同步:
1、在写入数据时,内存与磁盘之间有一块缓冲区,目的是为了降低磁盘的读写次数、提高读写效率
2、但是这种机制带来的后果是磁盘中的数据与实际写入的数据可能不符合,系统提供了三个函数让缓冲区中的数据立即写入磁盘,称为文件同步
fsync\sync\fdataync

文件属性:
    int stat(const char *pathname, struct stat *buf);
    功能:根据文件路径获取文件的属性
    buf:输出型参数
    int fstat(int fd, struct stat *buf);
    功能:根据文件描述符获取文件的属性
    int lstat(const char *pathname, struct stat *buf);
    功能:根据文件路径获取软链接文件的属性
    struct stat {
        dev_t     st_dev;         // 设备ID
        ino_t     st_ino;         // inode节点号
        mode_t    st_mode;        // 文件的类型和权限
        nlink_t   st_nlink;       // 硬链接数
        uid_t     st_uid;         // 用户ID
        gid_t     st_gid;         // 组ID
        dev_t     st_rdev;        // 特殊设备ID
        off_t     st_size;        // 总字节数
        blksize_t st_blksize;     // IO块总字节数
        blkcnt_t  st_blocks;      // 占用大小512字节的内存块数量
        struct timespec st_atim;  // 最后访问时间
        struct timespec st_mtim;  // 最后修改时间
        struct timespec st_ctim;  // 最后状态修改时间

        #define st_atime st_atim.tv_sec      /* Backward compatibility */
        #define st_mtime st_mtim.tv_sec
        #define st_ctime st_ctim.tv_sec
    };
文件的权限:
    int access(const char *pathname, int mode);
    功能:测试当前用户对文件的权限
    pathname:想要测试的文件路径
    mode:想要测试的权限
        F_OK    测试文件是否存在
        R_OK    测试文件是否有读权限
        W_OK    测试文件是否有写权限
        X_OK    测试文件是否有执行权限
    返回值:存在返回0 不存在返回-1
    int chmod(const char *pathname, mode_t mode);
    功能:根据文件路径修改文件权限
    mode:由三个八进制数组成的权限掩码
        0xxx
        0644    0666   普通文件
        0755           可执行文件
    int fchmod(int fd, mode_t mode);
    功能:根据文件描述符修改文件权限
    权限屏蔽码:
        如果想让新创建(open\creat)的文件不具备某些权限,可以通过设置权限屏蔽码进行屏蔽权限
        查看命令 umask 查看当前终端的权限屏蔽码
        注意:可以通过chmod命令、函数可以无视权限屏蔽码
        修改权限屏蔽码:
            命令:umask 0xxx 修改成0xxx
            注意:只是当前终端临时有效,如果想要长期有效需要修改配置文件
            函数:mode_t umask(mode_t mask);
                mask:新的屏蔽码
                返回值:原来的屏蔽码
            注意:该函数只是当前进程中生效,进程结束后就失效了
修改文件的大小:
    int truncate(const char *path, off_t length);
    功能:根据文件路径截取文件长度
    length:截取后文件的长度(字节)
    int ftruncate(int fd, off_t length);
    功能:根据文件描述符截取文件长度

文件删除、重命名:
int remove(const char *pathname);
功能:由C标准库提供的删除文件函数
int unlink(const char *pathname);
功能:操作系统提供的删除文件函数
remove底层调用unlink、rmdir函数
1、如果删除的是硬链接文件或者原文件本身且文件是关闭的,则是把该文件的硬链接数减1,然后清除该文件的inode信息
2、当文件的硬链接数减为0时,系统就把该文件的block权限释放,可以用于存储其它文件的数据
3、如果删除软链接文件,则删除的是软链接文件的inode信息,而不会删除原文件的数据,没有任何一个函数可以通过软链接文件删除源文件
int rename(const char *oldpath, const char *newpath);
功能:重命名文件

什么是软硬链接文件?
Linux文件系统会把分区分为两大部分:
inode信息块区:
每块默认128B,记录某个文件的文件权限、大小、所有者、修改时间等属性信息以及该文件的block信息
block数据块区:
每块默认4Kb,记录了文件的真正内容数据、文件名
每个文件有且只有一个inode信息块以及若干个block数据块,读取文件file需要借助所在目录文件的block中记录的file文件的inode号和文件名,来找到file的inode信息块,从而读取file文件的block数据块
硬链接文件:
没有属于自己的inode和block,只是在不同的目录下复制链接的源文件的inode信息块,通过该复制的inode信息块访问源文件的block数据块
软链接文件:
软链接文件会创建自己的新的inode和block块,在软链接文件的block中不存储源文件的数据,而是存储源文件的inode号,从而借助源文件的inode来访问源文件的block
区别:
1、删除源文件,只是删除源文件的inode信息块中的内容,对应的block的数据不会清理,所以硬链接文件依然可以访问,但是软链接文件就无法访问了
2、当文件的硬链接数删除到0时,文件才算被真正的删除了
3、修改硬链接文件的内容,源文件也会随之修改
4、硬链接不能链接目录、软链接可以
5、硬链接不能跨文件系统使用,而软链接可以
int link(const char *oldpath, const char *newpath);
功能:创建硬链接文件
int symlink(const char *target, const char *linkpath);
功能:创建软链接文件 文件类型 l

目录操作:
    int mkdir(const char *pathname, mode_t mode);
    功能:创建空目录
    mode:目录的权限,必须有执行权限才能进入目录
    返回值:成功0 失败-1
    int rmdir(const char *pathname);
    功能:删除空目录
    int chdir(const char *path);
    功能:修改当前的工作路径为path 相当于cd
    char *getcwd(char *buf, size_t size);
    功能:获取当前进程的工作路径 相当于pwd

    DIR *opendir(const char *name);
    功能:根据目录路径打开目录
    返回值:成功返回一个目录流对象
    DIR *fdopendir(int fd);
    功能:根据目录文件描述符打开目录
    返回值:成功返回一个目录流对象

    注意:DIR目录流对象中记录了该目录中所有文件的信息
    struct dirent *readdir(DIR *dirp);
    功能:从目录流dirp中读取一条文件信息并返回
    struct dirent {
        ino_t  d_ino;       // inode号
        off_t  d_off;       // 距离下一条信息的字节数
        unsigned short d_reclen;  // 当前信息的字节数
        unsigned char  d_type;   // 文件类型
        char           d_name[256]; // 文件名
    };
    注意:readdir读取完一条信息后,会自动的指向下一条信息,只需要继续执行readdir即可读取下一条,直到返回值为NULL读取完毕

标签:文件,const,int,char,mode,操作,权限
From: https://www.cnblogs.com/wangqiuji/p/17617906.html

相关文章

  • ACCESS 分享一个使用数组来批量操作控件属性的技巧
    原代码如下:PrivateSubComSave_Click()'保存按钮IfComSave.Caption="编辑(自动保存)"ThenMe.Text160.Locked=FalseMe.Text138.Locked=FalseMe.FM入库单.Form.数量.Locked=FalseMe.FM入库单.Form.单价.Locked=False......
  • yaml-cpp生成yaml文件及解析yaml文件
    1) 源码编译及安装获取源码$git clone https://github.com/jbeder/yaml-cpp.git$cd yaml-cpp && mkdir build && cd build && cmake .. && make && make install使用样例:由于yaml格式文件与xml和json格式的文件类似,采用树形结构。Yaml对于树节点定义为No......
  • 银行电子密码器也远程管理吗?操作步骤如下
    企业需要在不同办公地点管理多个资金账户,能不能远程点按读取银行电子密码器呢?三个字,很简单!可以用密码点按器!有了它就可以自动输入密码和读取验证码!第一步用双面胶把密码器固定在点按器上,一台点按器最多可以管理六个密码器,第二步打开朝天椒软件,给点按器录入不同密码按键的位置坐标。......
  • vue3 + vite + vue-router 4.x项目在router文件中使用pinia报错
    1.背景vue-router4.x版本,想在路由文件中引入并使用pinia后报错如下:表面意思是getActivePinia()方法在pinia还没有激活的时候被调用,导致报错。2.解决方法在stores文件夹下新建pinia.js文件,用来引入并创建pinia实例。import{createPinia}from"pinia";const......
  • 前端shp文件写到本地时,原生的shp-write存在的不能写入多条数据及中文乱码问题
    shp-write·Doraemon22333/前端-码云-开源中国(gitee.com)参考(1)https://github.com/hwbllmnn/shp-write/tree/maintenance(2)https://blog.csdn.net/qq_37748236/article/details/131804606......
  • 让Photoshop支持.ICO文件格式
    需要安装一个文件插件ICOFormat.8bi。官方下载地址:http://www.telegraphics.net/sw/下载以后的存放路径:...\Required\Plug-ins\FileFormats参考网址:https://blog.csdn.net/weixin_44222492/article/details/101596183......
  • - 推导分页的原理 - 使用分页类(器) - cookie和session的介绍、token - Django操作coo
    推导分页原理分页:当我们要展示的数据特别多的时候,一页展示不完,这个时候我们需要把要展示的数据分成多页展示分页中需要的几个参数:1.总数据有多少条2.每页展示多少条数据(自己规定的20)3.一共展示多少页4.总页数=总数据量/每页展示多少条数据5.当前第几页(前端传过去的)......
  • Oracle常规操作
    Oracle常规操作创建表CREATETABLEt_user(idNUMBER(4),usernameVARCHAR2(20)NOTNULL,genderCHAR(1)DEFAULT'M',birthDATE);插入数据--插入指定的列INSERTINTOt_user(id,username,gender)VALUES(1,'pp0419','M');--使用......
  • cmd运行 sqlserver脚本文件(sql文件过大)
     cdC:\ProgramFiles(x86)\MicrosoftSQLServer\110\Tools\Binnsqlcmd-S.-Usa-P123456-dTZHQ-iE:\bak\sql.sql -S.代表本地sa为数据库用户名123456为数据库密码TZHQ为数据库名称E:\bak\sql.sql代表文件路径......
  • 安防视频监控平台EasyNVR页面无法上传授权文件,该如何进行授权?
    TSINGSEE青犀视频安防监控平台EasyNVR可支持设备通过RTSP/Onvif协议接入,并能对接入的视频流进行处理与多端分发,包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等多种格式。在智慧安防等视频监控场景中,EasyNVR可提供视频实时监控直播、云端录像、云存储、录像检索与回看、告警等视......