当前位置: 首页 > news >正文

io进程----文件io

目录

一丶概念

二丶特点

三丶函数

1.打开文件 open

2.关闭文件 close

3.读取文件 read

4.写入文件 write

5.文件定位操作

标准IO和文件IO区别

四丶获取文件属性

1.stat函数

2.获取文件类型

五丶目录操作


一丶概念

在posix(可移植操作系统接口)中定义的一组输入输出的函数

二丶特点

        1.没有缓冲机制,每次操作都会经过系统调用,效率比较低
        2.围绕文件描述符进行操作,文件描述符是非负整数,0 1 2 .......,依次分配
        3.默认打开三个文件描述符,0(标准输入),1(标准输出),2(标准错误)
        4.操作除了目录d以外任意类型的文件bc-lsp
        5.可移植性相对较差

问题:打开三个文件, 描述符分别是:3 4 5 ,关闭4以后,重新打开这个文件,描述符是几?

           答: 还是4,因为4在关闭以后就空闲下来,下次打开新文件默认分配4

问题:一个进程的文件描述符最大到几?最多能打开多少个文件描述符?最多能打开多少个文件?
           答: 一个进程的文件描述符最大到1023 (0-1023), 最多能打开1024个文件描述符, 最多能打开1021(1024-3)个文件。

三丶函数

1.打开文件 open

#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
功能:打开文件
参数:pathname:文件路径名flags:打开文件的方式O_RDONLY:只读O_WRONLY:只写O_RDWR:可读可写O_CREAT:创建O_TRUNC:清空O_APPEND:追加
返回值:成功:文件描述符失败:-1
当第二个参数中有O_CREAT选项时,需要给open函数传递第三个参数,指定创建文件的权限 
int open(const char *pathname, int flags, mode_t mode);
最后权限 = mode &(~umask)  
例如:指定权限为0666(8进制)
最终权限= 0666 & (~umask) = 0666 &(~0002) = 664666  => 110 110 110
&775     111 111 101664 	 110 110 100
打开文件方式对应表:

标准IO

文件IO

r

O_RDONLY
只读)

r+

O_RDWR
可读可写

w

O_WRONLY|O_CREAT|O_TRUNC
只写,不存在创建,存在清空

w+

O_RDWR|O_TRUNC|O_CREAT
可读可写,不存在则创建,存在清空

a

O_WRONLY|O_CREAT|O_APPEND
只写,不存在创建,存在则追加

a+

O_RDWR|O_CREAT|O_APPEND
可读可写,不存在创建,存在则追加

2.关闭文件 close

int close(int fd);
功能:关闭文件
参数:fd:文件描述符
#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;//1.打开文件//fd = open("a.c", O_RDONLY); //rfd = open("a.c", O_WRONLY | O_CREAT | O_TRUNC, 0666); //wif (fd < 0){perror("open err ");return -1;}printf("fd: %d\n", fd);//2.关闭文件close(fd);return 0;
}

3.读取文件 read

ssize_t read(int fd, void *buf, size_t count);
功能:从一个已打开的可读文件中读取数据
参数: fd  文件描述符buf  存放位置count  期望的个数
返回值:成功:实际读到的个数(小于期望值说明实际没这么多)返回0:表示读到文件结尾返回-1:表示出错,并设置errno号

4.写入文件 write

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
功能:向指定文件描述符中,写入 count个字节的数据。
参数:fd   文件描述符buf   要写的内容count  期望写入字节数
返回值:成功:实际写入数据的个数失败  : -1
练习:文件IO实现cp功能。cp 源文件 新文件名
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char const *argv[])
{if (argc != 3){printf("filename err");return -1;}int m = open(argv[1], O_RDWR);if (m < 0){printf("argv[1] err");return -1;}int n = open(argv[2], O_CREAT||O_TRUNC|O_WRONLY,0777);if (n < 0){printf("argv[2] err");return -1;}int buf[64];int i;while((i=read(m,buf,64))>0)//记录正确读取的个数,当读不到字符时停止读取{write(n,buf,i);//将正确读取的个数写入到n中}close(m);close(n);return 0;
}

5.文件定位操作

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
功能:设定文件的偏移位置
参数:fd:文件描述符offset偏移量  正数:向文件结尾位置移动负数:向文件开始位置whence   相对位置SEEK_SET   开始位置SEEK_CUR   当前位置SEEK_END   结尾位置
返回值:成功:文件的当前位置失败:-1
        练习:向文件中第 10 位置后面写一个字符,在文件此时的位置,往后移动20个位置处,写一行字符串hello进去,求此时文件的长度。
#include<stdio.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
int main(int argc, char const *argv[])
{int n;n=open("test.txt",O_RDWR);if (n < 0){printf("open err");return -1;}lseek(n,10,0);write(n,"a",1);lseek(n,20,1);write(n,"hello",5);off_t len=lseek(n,0,2);printf("%ld\n",len);return 0;
}

标准IO和文件IO区别

标准IO

文件IO

概念

在C库中定义的一组输入输出的函数

在posix中定义的一组输入输出的函数

特点

1.  有缓冲区,减少系统调用,提高效率

2.  围绕流操作,FILE*

3.  默认打开三个流:stdin\stdout\stderr

4.  只操作普通文件

1.  没有缓冲区,每次操作都引起系统调用

2.  围绕文件描述符操作

3.  默认打开三个文件描述符:0\1\2

4.  除目录外其他文件

函数

打开文件:fopen/freopen

关闭文件:fclose

读写文件:fgetc/fputc fgets/fputs fread/fwrite

文件定位:rewind/fseek/ftell

打开文件:open

关闭文件:close

读写文件:read/write

文件定位:lseek

四丶获取文件属性

1.stat函数

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>int stat(const char *path, struct stat *buf);
功能:获取文件属性
参数:  path:文件路径名buf:保存文件属性信息的结构体
返回值:成功:0失败:-1struct stat {ino_t     st_ino;     /* inode号 ls -il */     mode_t    st_mode;    /* 文件类型和权限 */nlink_t   st_nlink;   /* 硬链接数 */uid_t     st_uid;     /* 用户ID */gid_t     st_gid;     /* 组ID */off_t     st_size;    /* 大小 */time_t    st_atime;   /* 最后访问时间 */time_t    st_mtime;   /* 最后修改时间 */time_t    st_ctime;   /* 最后状态改变时间 */};

文件权限和类型需要通过位操作获取:

st_mode 主要包含了 3 部分信息:
a. 15bit ~ 12bit 保存文件类型
b. 11bit ~ 9bit 保存执行文件时设置的信息(不用管)
c. 8bit ~ 0bit 保存文件访问权限

2.获取文件类型

        S_IFMT是一个掩码,它的值是0170000(注意这里用的是八进制前缀为0,二进制0b001111000000000000), 可以用来把st_mode位与上掩码过滤提取出表示的文件类型的那四位(15bit~12bit位),也就是这四位原样获取其他位清零。

这四位可以表示0b0000~0b1111(八进制表示:001~014)七个值,每个值分别对应不同的文件类型:套接字文件、符号链接文件、普通文件、块设备、目录、字符设备、管道。

        判断一个文件是不是普通文件,首先通过掩码S_IFMT把其他无关的部分置0,再与表示普通文件的数值比较,从而判断这是否是一个普通文件:

或者用switch

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{struct stat *st = (struct stat *)malloc(sizeof(struct stat));if (stat("0.c", st) != 0){printf("stat err\n");return -1;}printf("idode:%ld\n", st->st_ino);printf("nlink:%ld\n", st->st_nlink);printf("size:%ld\n", st->st_size);printf("mode:%#o\n", st->st_mode);if (st->st_mode & __S_IFMT == __S_IFDIR)printf("目录\n");if (st->st_mode & __S_IFMT == __S_IFREG)printf("普通文件\n");for (int i = 8; i >= 0; i--){if (st->st_mode & (1 << i)){switch (i % 3){case 2:printf("r");break;case 1:printf("w");break;case 0:printf("x");break;}}elseprintf("-");}printf("\n");return 0;
}

五丶目录操作

围绕着目录流进行操作,DIR *
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能:获得目录流
参数:要打开的目录
返回值:成功:目录流失败:NULLstruct dirent *readdir(DIR *dirp);
功能:读目录
参数:要读的目录流
返回值:成功:读到的信息    失败或读到目录结尾:NULL
返回值为结构体,该结构体成员为描述该目录下的文件信息struct dirent {ino_t   d_ino;               /* 索引节点号*/off_t   d_off;               /*在目录文件中的偏移*/unsigned short d_reclen;    /* 文件名长度*/unsigned char  d_type;      /* 文件类型 */char    d_name[256];       /* 文件名 */
};int closedir(DIR *dirp);
功能:关闭目录
参数:dirp:目录流

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 8月27日,每日信息差
  • 【深度学习】爱因斯坦求和约定
  • STM32 - 笔记3
  • 最新网站服务器CC压力测试系统源码
  • 开源 AI 智能名片 O2O 商城小程序在社交私域中的圈层价值
  • 【卡梅德生物】羊驼单抗定制:从单B细胞筛选到应用
  • Web开发:通过Quatz开启定时任务调度的基础demo
  • 【JVM】垃圾回收算法(一)
  • c++核心编程指南
  • k8s备份etcd3.5
  • jenkins任务中无法执行sudo,管理员操作
  • 分块矩阵的转置
  • Vue3源码调试-第二篇
  • 跨界融合:Scratch与硬件的创新集成
  • 网站上线3个多月了,还没有被百度收录怎么办?
  • JavaScript-如何实现克隆(clone)函数
  • 「前端早读君006」移动开发必备:那些玩转H5的小技巧
  • Create React App 使用
  • docker-consul
  • IDEA 插件开发入门教程
  • Markdown 语法简单说明
  • Python3爬取英雄联盟英雄皮肤大图
  • Selenium实战教程系列(二)---元素定位
  • SpiderData 2019年2月25日 DApp数据排行榜
  • Spring框架之我见(三)——IOC、AOP
  • vue数据传递--我有特殊的实现技巧
  • 工程优化暨babel升级小记
  • 力扣(LeetCode)965
  • 聊聊directory traversal attack
  • 前端存储 - localStorage
  • 微信小程序开发问题汇总
  • 【运维趟坑回忆录】vpc迁移 - 吃螃蟹之路
  • 宾利慕尚创始人典藏版国内首秀,2025年前实现全系车型电动化 | 2019上海车展 ...
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • ​Java并发新构件之Exchanger
  • ​如何使用QGIS制作三维建筑
  • # 数据结构
  • ######## golang各章节终篇索引 ########
  • #考研#计算机文化知识1(局域网及网络互联)
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (2024,RWKV-5/6,RNN,矩阵值注意力状态,数据依赖线性插值,LoRA,多语言分词器)Eagle 和 Finch
  • (6)设计一个TimeMap
  • (二)【Jmeter】专栏实战项目靶场drupal部署
  • (二)构建dubbo分布式平台-平台功能导图
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (回溯) LeetCode 46. 全排列
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (五十)第 7 章 图(有向图的十字链表存储)
  • (一)UDP基本编程步骤
  • (转)大道至简,职场上做人做事做管理
  • .NET CORE使用Redis分布式锁续命(续期)问题
  • .NET DevOps 接入指南 | 1. GitLab 安装