网站访客qq抓取统计系统,敖降网站建设,建设网站的免费模板,wordpress默认文章缩略图#x1f440;樊梓慕#xff1a;个人主页 #x1f3a5;个人专栏#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》
#x1f31d;每一个不曾起舞的日子#xff0c;都是对生命的辜负 目录
前言
1.C语言文件IO
1.1…
樊梓慕个人主页 个人专栏《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》
每一个不曾起舞的日子都是对生命的辜负 目录
前言
1.C语言文件IO
1.1C语言文件IO接口汇总
1.2当前路径指的是什么 1.3stdin、stdout、stderr
2.系统文件IO
2.1open
参数const char* pathname
参数int flags
*位图方式传参
参数mode_t mode
返回值int fd『 简要理解文件描述符』
2.2close
2.3write
2.4read 前言
进程周边的相关内容暂时告一段落下面我们开始学习文件部分。
学习『 系统文件IO』之前我会与大家先复习一下C语言部分文件IO的相关接口为后面的学习作『 铺垫』。系统文件IO部分本篇文章会讲解『 基本的系统调用』open()、close()、read()、write()有关参数传递涉及到『 位图方式传递』这部分以前没有学习过博主也会拿出来简单的学习一下。 欢迎大家收藏以便未来做题时可以快速找到思路巧妙的方法可以事半功倍。 GITEE相关代码fanfei_c的仓库 1.C语言文件IO
1.1C语言文件IO接口汇总
在学习C语言期间我们学习过一些C语言封装的文件接口
C语言文件接口汇总 打开文件关闭文件写入一个字符读取一个字符写入一个字符串读取一个字符串格式化写入数据格式化读取数据向二进制文件写入数据从二进制文件读取数据设置文件指针的位置计算当前文件指针相对于起始位置的偏移量设置文件指针到文件的起始位置判断文件操作过程中是否发生错误判断文件指针是否读取到文件末尾
本篇文章不会完全的讲解以上C语言文件接口想要详细了解的同学可以『 点击以下内容』跳转到博主的有关C语言文件IO的博客。
『 樊梓慕』文件操作——CSDNhttp://t.csdnimg.cn/DRPJb
1.2当前路径指的是什么
当我们利用C语言IO接口创建文件时生成的文件默认在『 当前路径』可当前路径具体指的是谁的路径呢
『 文件是由进程创建』所以文件的当前路径也是进程的当前路径。
在之前学习进程的部分我们已经聊过有关话题当前路径指的是进程在启动时会保存当前目录的路径保存到『 /proc/[pid]/cwd』中该路径就是进程的当前路径。 1.3stdin、stdout、stderr
在之前学习时我们提到过一个概念『 Linux下一切皆文件』 也就是说键盘、显示器都是文件这很好理解我们向普通文件写入本质上就是向磁盘写入数据那将对象改为显示器是不是就是打印了
但是向文件写入我们一般这么操作
FILE* fp fopen(log.txt, w);
fputs(hello world\n, fp);
可是打印我们从未『 打开』显示器文件也从未『 传递』过流参数
printf(hello world\n);
这也就说明了
进程在运行的时候都会『 默认打开』三个输入输出流即标准输入流、标准输出流以及标准错误流对应到C语言当中就是stdin、stdout以及stderr。
其中标准输入流对应的设备就是键盘标准输出流和标准错误流对应的设备都是显示器。
所以我们想要实现打印的功能也可以这样写
fputs(hello world\n, stdout); stdin、stdout以及stderr是C标准库下的标准输入输出错误流其他语言如C也有对应的标准输入输出错误流cin、cout和cerr。 2.系统文件IO C程序可以直接对硬件进行写入么
在之前学习的时候关于操作系统我们有过这样一张图 什么意思
程序不可能也不可以越过操作系统直接操作硬件还记得『 系统调用』么 也就是说C标准库中的文件IO接口一定『 封装了系统调用』所以才能利用fopen()、fputs()等函数对文件进行操作。
那接下来我们就来学习文件IO的系统调用。
2.1open open是打开文件的系统调用接口。
int open(const char *pathname, int flags, mode_t mode);
参数const char* pathname
代表要打开或创建的目标文件。
若pathname以路径的方式给出则当需要创建该文件时就在pathname路径下进行创建。若pathname以文件名的方式给出则当需要创建该文件时默认在当前路径下进行创建。
参数int flags
代表文件的打开方式。
参数含义O_RDONLY以只读的方式打开文件O_WRNOLY以只写的方式打开文件O_APPEND以追加的方式打开文件O_RDWR以读写的方式打开文件O_CREAT当目标文件不存在时创建文件
传递方式介绍
例如以只写的方式打开文件当目标文件不存在时自动创建文件则参数设置如下
O_WRONLY | O_CREAT
为什么这么传递
*位图方式传参 先写一段代码
#define ONE 1
#define TWO (11)
#define THREE (12)
#define FOUR (13)
#define FIVE (14)void Print(int flag)
{if(flag ONE) printf(1\n);if(flag TWO) printf(2\n);if(flag THREE) printf(3\n);if(flag FOUR) printf(4\n);if(flag FIVE) printf(5\n);
}int main()
{Print(ONE);printf(----------------------\n);Print(TWO);printf(----------------------\n);Print(ONE|TWO);printf(----------------------\n);Print(THREE|FOUR|FIVE);printf(----------------------\n);Print(ONE|TWO|THREE|FOUR|FIVE);
} 根据代码中的宏定义这些宏的特点就是所有位加起来只有一个1。 Print函数中五个if中的判断条件其实就是判断参数哪个位为1如果传的是ONE那么ONE与ONE得到的就是1为真就打印1其余的都为假不打印。
当带上|操作符后相当于把两个参数的1位合并到一起比如ONE|TWO得到的就是0011所以在Print中就会满足两个条件flag ONE 和 flag TWO。 这就是位图方式传参的基本思想。 放到flags中呢
#define O_RDONLY 0000
#define O_WRONLY 0001
#define O_RDWR 0010
#define O_CREAT 0100
之后通过运算
int open(arg1, arg2, arg3){if (arg2O_RDONLY){//设置了O_RDONLY选项}if (arg2O_WRONLY){//设置了O_WRONLY选项}if (arg2O_RDWR){//设置了O_RDWR选项}if (arg2O_CREAT){//设置了O_CREAT选项}//...
}
所以如果arg2O_CREAT | O_WRONLY即arg20101arg2 O_WRONLY 1 arg2 O_CREAT 1就达到了『 以只写的方式打开文件当目标文件不存在时自动创建文件』的目的。
这就是『 位图方式传参』。
参数mode_t mode
代表创建文件的默认权限。
例如将mode设置为0666则创建出来的文件权限如下
-rw-rw-rw-
但『 实际上』创建出来文件的权限值还会受到umask文件默认掩码的影响。
实际创建出来文件的权限为mode减去对应位的umask值。
umask的默认值默认为0002所以当我们设置mode值为0666时实际创建出来文件的权限为0664。
若想创建出来文件的权限值不受umask的影响则需要在创建文件前使用umask函数将文件默认掩码设置为0。
umask(0); //将文件默认掩码设置为0
如果不需要创建新的文件则使用两个参数的open即可。
返回值int fd『 简要理解文件描述符』
代表打开文件的『 文件描述符』。
fd0返回的是文件描述符。fd-1代表打开文件失败。
一个进程可以打开多个文件
#include stdio.h
#include sys/stat.h
#include sys/types.h
#include fcntl.h
int main()
{umask(0);int fd1 open(log1.txt, O_RDONLY | O_CREAT, 0666);int fd2 open(log2.txt, O_RDONLY | O_CREAT, 0666);int fd3 open(log3.txt, O_RDONLY | O_CREAT, 0666);int fd4 open(log4.txt, O_RDONLY | O_CREAT, 0666);int fd5 open(log5.txt, O_RDONLY | O_CREAT, 0666);printf(fd1:%d\n, fd1);printf(fd2:%d\n, fd2);printf(fd3:%d\n, fd3);printf(fd4:%d\n, fd4);printf(fd5:%d\n, fd5);return 0;
}为什么是从3开始呢
我们刚才讲进程默认会打开三个输入输出流标准输入流、标准输出流、标准错误流。
所以0、1、2分别代表了它们。
从而我们得到文件描述符的分配规则
找到当前没有被使用的最小的下标作为新的文件描述符。 2.2close
close是关闭文件的系统调用接口。
int close(int fd);//参数fd是文件描述符
关闭文件成功返回0关闭文件失败返回-1。
2.3write
write是写入文件的系统调用接口。
ssize_t write(int fd, const void *buf, size_t count);
功能将buf位置开始向后count字节的数据写入文件描述符为fd的文件当中。
写入成功返回写入数据的字节个数。写入失败返回-1。
例如
#include stdio.h
#include string.h
#include unistd.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
int main()
{int fd open(log.txt, O_WRONLY | O_CREAT, 0666);if (fd 0){perror(open);return 1;}const char* msg hello syscall\n;for (int i 0; i 5; i){write(fd, msg, strlen(msg));}close(fd);return 0;
}2.4read
read是读取文件的系统调用接口。
ssize_t read(int fd, void *buf, size_t count);
功能从文件描述符为fd的文件读取count字节的数据到buf位置当中。
读取成功返回读取数据的字节个数。读取失败返回-1。
例如
#include stdio.h
#include string.h
#include unistd.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
int main()
{int fd open(log.txt, O_RDONLY);if (fd 0){perror(open);return 1;}char ch;while (1){ssize_t s read(fd, ch, 1);if (s 0){break;}write(1, ch, 1); //向文件描述符为1的文件写入数据即向标准输出流显示器写入数据}close(fd);return 0;
}当然对于文件管理来说还有很多需要讲解的细节博主会放到下一篇文章中详细讲解下一篇文章会深入学习『 Linux系统是如何管理文件的』『 文件描述符在其中又扮演了怎样的角色』『 怎么理解Linux下一切皆文件』等等内容本篇文章只是文件部分的简单开头主要目的是为了『 作铺垫』更多内容请持续关注博主Linux系列文章。 如果你对该系列文章有兴趣的话欢迎持续关注博主动态博主会持续输出优质内容
博主很需要大家的支持你的支持是我创作的不竭动力
~ 点赞收藏关注 ~