文件操作

  • 1、系统调用概述
  • 2、系统调用 和 库函数的区别(重要!!!)
  • 3、文件描述符(重要!!!)
    • 案例:读取文件数据
  • 4、文件的打开读写关闭
    • 4.1、打开文件open
      • 4.1.1、flags宏的介绍(打开方式)
      • 4.1.2、mode的介绍(权限)
    • 4.2、关闭文件close
      • 案例:
    • 4.3、文件的写操作write
    • 4.4、read读取文件数据
      • 案例:读文件数据
      • 案例:实现cp命令: cp src_file dst_dir
  • 5、文件的阻塞特性
    • 案例:默认终端是读是阻塞的
    • 案例:非阻塞()
    • 5.1、通过fcntl函数设置文件的阻塞特性(了解)
      • 案例:默认阻塞
  • 6、通过文件名 直接获取文件的状态(了解)
    • 案例:
  • 7、文件的目录操作(了解)
    • 1、打开文件目录opendir
    • 2、读取目录readdir 调用一次 只能读取一个文件
    • 3、关闭closedir
    • 案例:

1、系统调用概述

系统调用,顾名思义,说的是操作系统提供给用户程序调用的一组“特殊”接口。(重要!!!)
一个进程(用户态、内核态)(了解)

2、系统调用 和 库函数的区别(重要!!!)



系统调用是需要时间的,程序中频繁的使用系统调用会降低程序的运行效率。当运行内核代码时,CPU工作在内核态,在系统调用发生前需要保存用户态的栈和内存环境,然后转入内核态工作。系统调用结束后,又要切换回用户态。这种环境的切换会消耗掉许多时间 。

3、文件描述符(重要!!!)

用一个非负整数 来标识一个文件 这个非负的整数 就是文件描述符。
打开一个文件 系统就会为我们非配一个文件描述符 操作文件描述符 就等价于 操作文件.

文件描述符表:进程运行的时候 系统创建文件描述符表 来管理系统中文件描述符。
每一个进程 默认打开了3个文件描述符(0标准输入设备/键盘 1标准输出设备/屏幕 2标准错误输出/屏幕)

案例:读取文件数据



运行结果:


当用户打开一个文件的时候 系统 会给我们分配一个最小可用的文件描述符(重要!!!)

文件描述符表的管理(位图)

4、文件的打开读写关闭

4.1、打开文件open

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);//打开已存在的文件
int open(const char *pathname, int flags, mode_t mode);//打开不存在的文件
//flags:read write操作文件的权限
//mode:该文件在磁盘中 相对于 用户的权限
功能:打开文件,如果文件不存在则可以选择创建。
参数:pathname:文件的路径及文件名flags:打开文件的行为标志,必选项 O_RDONLY, O_WRONLY, O_RDWRmode:这个参数,只有在文件不存在时有效,指新建文件时指定文件的权限
返回值:成功:成功返回打开的文件描述符失败:-1

4.1.1、flags宏的介绍(打开方式)

比如:以读写的方式打开 不存在则创建 存在清空 flags=O_RDWR | O_CREAT | O_TRUNC

4.1.2、mode的介绍(权限)

mode的权限分3组:所拥有者、同组用户、其他用户
每组都必须有独立的权限。

4表示读r 2表示写w 1表示可执行x


文件的最终权限 = 默认权限 - 文件掩码
文件掩码:屏蔽其他用户的权限



chmod 777 xxx将xxx的最终权限设置为777

4.2、关闭文件close

#include <unistd.h>
int close(int fd);
功能:关闭已打开的文件
参数:fd : 文件描述符,open()的返回值
返回值:成功:0失败: -1, 并设置errno

案例:


运行结果:

4.3、文件的写操作write

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
功能:把指定数目的数据写到文件(fd)
参数:fd :  文件描述符buf : 数据首地址count : 写入数据的长度(字节)
返回值:成功:实际写入数据的字节个数失败: - 1

4.4、read读取文件数据

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
功能:把指定数目的数据读到内存(缓冲区)
参数:fd : 文件描述符buf : 内存首地址count : 读取的字节个数
返回值:成功:实际读取到的字节个数失败: - 1 文件末尾返回0

案例:读文件数据

案例:实现cp命令: cp src_file dst_dir

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{//./main test.txt  testif(argc != 3){printf("please intput:./main src dst_dir\n");}char src_file[128]="";char dst_file[128]="";strcpy(src_file, argv[1]);//test.txtsprintf(dst_file,"%s/%s",argv[2], argv[1]);//"test/test.txt"int fd1 = open(src_file, O_RDONLY);if(fd1 < 0){perror("open");return 0;}int fd2 = open(dst_file, O_WRONLY|O_CREAT,0777);if(fd2 <0){perror("open");return 0;}while(1){char buf[128]="";//从s源文件中读取数据int ret = read(fd1,buf,sizeof(buf));if(ret <= 0)break;//将读到的w数据写到目的文件中write(fd2,buf,ret);}close(fd1);close(fd2);return 0;
}

运行结果:

5、文件的阻塞特性

【注意】阻塞与非阻塞是对于文件而言的,而不是指read、write等的属性

案例:默认终端是读是阻塞的

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(int argc,char *argv[])
{// /dev/tty --> 当前终端设备int fd = open("/dev/tty", O_RDONLY);//默认是阻塞的if(fd<0){perror("open");return 0;}printf("fd = %d\n",fd);char buf[128]="";printf("准备读!!!\n");read(fd,buf,sizeof(buf));printf("buf=%s\n",buf);close(fd);return 0;
}

运行结果:

案例:非阻塞()

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(int argc,char *argv[])
{// /dev/tty --> 当前终端设备//int fd = open("/dev/tty", O_RDONLY);//默认是阻塞的int fd = open("/dev/tty", O_RDONLY|O_NONBLOCK);//不阻塞的if(fd<0){perror("open");return 0;}printf("fd = %d\n",fd);char buf[128]="";printf("准备读!!!\n");read(fd,buf,sizeof(buf));printf("buf=%s\n",buf);close(fd);return 0;
}

运行结果:

5.1、通过fcntl函数设置文件的阻塞特性(了解)

我们还可以通过fcntl函数来设置文件描述符的阻塞特性
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */);
功能:改变已打开的文件性质,fcntl针对描述符提供控制。
参数:fd:操作的文件描述符cmd:操作方式arg:针对cmd的值,fcntl能够接受第三个参数int arg。
返回值:成功:返回某个其他值失败:-1
fcntl函数有5种功能:
1) 复制一个现有的描述符(cmd=F_DUPFD)
2) 获得/设置文件描述符标记(cmd=FGETFD或FSETFD)
3) 获得/设置文件状态标记(cmd=FGETFL或FSETFL)
4) 获得/设置异步I/O所有权(cmd=FGETOWN或FSETOWN)
5) 获得/设置记录锁(cmd=FGETLK, FSETLK或F_SETLKW)

案例:默认阻塞


fcntl函数设置非阻塞

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(int argc,char *argv[])
{char buf[128]="";//fcntl设置文件标记的3步曲//获得文件的标记int flag = fcntl(0, F_GETFL);//修改文件的标记(非阻塞标记)flag |= O_NONBLOCK;//设置文件的标记fcntl(0,F_SETFL, flag);printf("准备读!!!\n");read(0,buf,sizeof(buf));printf("buf=%s\n",buf);    return 0;
}

运行结果:

6、通过文件名 直接获取文件的状态(了解)

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
int lstat(const char *pathname, struct stat *buf);
功能:获取文件状态信息stat和lstat的区别:当文件是一个符号链接时,lstat返回的是该符号链接本身的信息;而stat返回的是该链接指向的文件的信息。
参数:path:文件名buf:保存文件信息的结构体
返回值:成功: 0失败: -1

struct stat的结构信息:

struct stat {dev_t           st_dev;     //文件的设备编号ino_t           st_ino;     //节点mode_t          st_mode;            //文件的类型和存取的权限nlink_t         st_nlink;       //连到该文件的硬连接数目,刚建立的文件值为1uid_t           st_uid;     //用户IDgid_t           st_gid;     //组IDdev_t           st_rdev;        //(设备类型)若此文件为设备文件,则为其设备编号off_t           st_size;        //文件字节数(文件大小)blksize_t       st_blksize;     //块大小(文件系统的I/O 缓冲区大小)blkcnt_t        st_blocks;      //块数time_t          st_atime;       //最后一次访问时间time_t          st_mtime;       //最后一次修改时间time_t          st_ctime;       //最后一次改变时间(指属性)
};

st_mode(16位整数)参数说明:


案例:

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(int argc,char *argv[])
{struct stat my_stat;stat("test.txt", &my_stat);printf("文件的大小:%u\n", my_stat.st_size);if(S_ISREG(my_stat.st_mode)){printf("它是一个普通文件\n");}else if(S_ISDIR(my_stat.st_mode)){printf("它是一个目录文件\n");}if((my_stat.st_mode& S_IRUSR)== S_IRUSR){printf("所有者具备读的权限\n");}return 0;
}

运行结果:

7、文件的目录操作(了解)

我们经常需要读取一个目录下的所有文件名,所以一下介绍如何读取一个文件下的目录
步骤:

1、打开文件目录opendir

#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能:打开一个目录
参数:name:目录名
返回值:成功:返回指向该目录结构体指针失败:NULL

2、读取目录readdir 调用一次 只能读取一个文件

#include <dirent.h>
struct dirent *readdir(DIR *dirp);
功能:读取目录
参数:dirp:opendir的返回值
返回值:成功:目录结构体指针失败:NULL

struct dirent:

struct dirent
{ino_t d_ino;                  // 此目录进入点的inodeoff_t d_off;                    // 目录文件开头至此目录进入点的位移signed short int d_reclen;      // d_name 的长度, 不包含NULL 字符unsigned char d_type;           // d_type 所指的文件类型char d_name[256];               // 文件名
};

d_type取值:

3、关闭closedir

#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
功能:关闭目录参数:dirp:opendir返回的指针返回值:成功:0失败:-1

案例:

#include <stdio.h>
#include <dirent.h>
int main(int argc,char *argv[])
{//打开目录DIR *dir = opendir("test");if(dir == NULL){perror("opendir");return 0;}//读取目录while(1){struct dirent *p = readdir(dir);if(p == NULL)break;printf("文件名:%s  ", p->d_name);if(p->d_type == DT_DIR){printf("目录\n");}else if(p->d_type == DT_REG){printf("普通文件\n");}}//关闭closedir(dir);
}

运行结果:

Linux文件IO操作相关推荐

  1. 嵌入式 Linux 文件IO操作

    目录 Linux 文件操作 1 Linux 系统环境文件操作概念 2 缓冲 IO 文件操作 1 文件的创建,打开与关闭 fopen 函数函数 2 freopen 函数 3.fdopen函数 4.fcl ...

  2. linux的文件io操作(转)

    linux文件IO操作有两套大类的操作方式:不带缓存的文件IO操作,带缓存的文件IO操作.不带缓存的属于直接调用系统调用(system call)的方式,高效完成文件输入输出.它以文件标识符(整型)作 ...

  3. 漫谈linux文件io,Linux文件IO与通用块层的请求合并

    本文参考https://mp.weixin.qq.com/s/Imt4BW-zoHPpcOpcKZs_AQ, 公众号"Linux阅码场" 请求合并就是将进程内或者进程间产生的在物理 ...

  4. 【Linux系统编程】文件IO操作

    文件描述符 在 Linux 的世界里,一切设备皆文件.我们可以系统调用中 I/O 的函数(I:input,输入:O:output,输出),对文件进行相应的操作( open().close().writ ...

  5. Linux基础(6)--文件IO操作

    文件IO操作 1. open打开操作 2. close关闭操作 3. creat创建操作 4. write写操作 5. read读操作 Linux下一切皆文件,所以文件IO是很重要的也是很基础的操作. ...

  6. linux的每次IO大小控制,linux文件io缓冲

    linux文件io缓冲 出于速度和效率考虑,系统io调用(即内核)和标准 C语言库的io函数(即 stdin 函数)在操作磁盘文件时会对数据进行缓冲. read(),write()系统调用在操作磁盘文 ...

  7. Linux文件IO深入剖析

    文章目录 1 linux文件系统基本概念 1.1 文件系统基本概念 1.2 文件系统缓存 2 文件IO访问方式概述 2.1 标准文件IO 2.2 直接IO 2.3 缓存同步 1 linux文件系统基本 ...

  8. Linux 文件 IO

    参考:http://blog.csdn.net/wanxiao009/article/details/5648583 C 和 C++ 文件操作详解:http://blog.csdn.net/freek ...

  9. 2.Linux文件IO编程

    2.1Linux文件IO概述 2.1.0POSIX规范 POSIX:(Portable Operating System Interface)可移植操作系统接口规范. 由IEEE制定,是为了提高UNI ...

  10. 浅析 Linux 文件 IO 读写

    浅析 Linux 文件 IO 读写 Linux的文件IO子系统是Linux中最复杂的一个子系统(没有之一).读者可以参考以下这个图: https://www.thomas-krenn.com/de/w ...

最新文章

  1. 宁可寸寸断,不意绕指柔
  2. 【OC】【一秒就会】【collectionView 头部吸住功能】
  3. [菜鸟SpringCloud实战入门]第七章:配置中心客户端主动刷新机制 + 配置中心服务化和高可用改造...
  4. 455. 分发饼干 golang
  5. Spring入门篇——第6章 Spring AOP的API介绍
  6. 【英语学习】【English L06】U02 Food L1 Food on the menu
  7. 理解分布式和集群的区别
  8. java家谱树_青锋家谱系统-基于springboot+orgtree的青锋家谱树管理系统
  9. java 数据类型 面试题_Java数据类型面试题目
  10. mysql必知必会第4版pdf百度网盘_SQL必知必会 第4版pdf
  11. 网上鞋店html,“鞋店”是“shoes store”还是“shoe store”?
  12. 樱花树代码html,樱花树代码
  13. android 查看cad方案,android 加载dwg 图纸解决方案
  14. c语言优先级详解pdf,C语言符号优先级.pdf
  15. Win10 设置锁屏壁纸提示尝试其它图片
  16. python 计算置信区间_python 计算数据中值的置信区间
  17. 【Python】计算VOC格式XML文件中目标面积和长宽比并生成直方图
  18. html显示一条直线,如何在HTML中画一条线
  19. 局域网环境下的直播平台(校园电视台)搭建之路
  20. 进程间通信——消息队列(Message queue)

热门文章

  1. 2021-01-19第二次Sping Boot学习汇报--利用用Spring Initializr构建项目
  2. macos双系统 wintogo_aigo固态硬盘,轻松实现macOS运行Windows双系统
  3. vue中使用 minix 混入
  4. L1 和 L2的区别
  5. 电脑误删wps文件怎么恢复?介绍4个解决方法
  6. 计算机软件高级职称有啥用,计算机软考高级职称有什么用
  7. 索尼Z2(L50t)刷CM12教程
  8. 怎么删除微信的手机充值服务器,微信怎么开启和取消自动充值话费功能?
  9. RadioButton 只读
  10. 打开OFFICE文件是只读属性