【Linux】—— 在Linux上进行读写文件操作

前言:

  • 在之前,我已经对进程的相关知识进行了详细的介绍。本期开始,我们将要学习的是关于 “基础I/O”的知识!!!

目录

(一)C文件接口

 (二)系统文件I/O

1、接口介绍

2、代码示例

(三)总结


(一)C文件接口

首先,在正式进入本期主题之前,我先用C文件的接口带大家简单的回顾下,顺便带大家认识相关的接口函数等。

首先就是往文件里面进行写数据操作:

#include <stdio.h>
#include <string.h>#define LOG "log.txt"int main()
{FILE *fp = fopen(LOG , "w");if(!fp){perror("fopen");return 1;}const char *msg = "hello bit!\n";int count = 5;while(count--){//fputs(msg,fp);fwrite(msg, strlen(msg), 1, fp);}fclose(fp);return 0;
}

输出展示:

【解释说明】

  1. 上述代码简单的实现了打开文件、写入文本内容,并关闭文件。在系统中,提供了丰富的用于对文件进行操作的函数;
  2. 打开文件使用 fopen 函数以写入模式打开文件,返回一个文件指针 fp;
  3. 如果文件打开失败,perror 函数将输出错误信息到标准错误输出流。
  4. 其次使用fwrite函数将字符串msg通过文件指针fp写入文件(除了这个外还有很多)

首先就是读文件里面的数据操作:

#define LOG "log.txt"int main()
{FILE *fp = fopen(LOG, "r");if(!fp){perror("fopen");return -1;}//正常进行文件操作while(1){char line[128];if(fgets(line, sizeof(line), fp) == NULL) break;else printf("%s", line);}fclose(fp);return 0;
}

输出展示:

【解释说明】

  • 同样的对于读文件操作,在系统内部也提供的很多的函数去进行实现!

如上,是我们之前学的文件相关操作。还有 fseek ftell rewind 的函数。


 (二)系统文件I/O

操作文件,除了上述C接口(当然,C++也有接口,其他语言也有),我们还可以采用系统接口来进行文件访问.

先来直接以代码的形式,实现和上面一模一样的代码(写操作):

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main()
{umask(0);int fd = open("myfile", O_WRONLY|O_CREAT, 0644);if(fd < 0){perror("open");return 1;}int count = 5;const char *msg = "hello bit!\n";int len = strlen(msg);while(count--){write(fd, msg, len);//fd: 后面讲, msg:缓冲区首地址, len: 本次读取,期望写入多少个字节的数据。 //返回值:实际写了多少字节数据}close(fd);return 0;
}
  • C++中对文件进行读操作可写成下述:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main()
{int fd = open("myfile", O_RDONLY);if(fd < 0){perror("open");return 1;}const char *msg = "hello bit!\n";char buf[1024];while(1){ssize_t s = read(fd, buf, strlen(msg));//类比writeif(s > 0){printf("%s", buf);}else{break;}}close(fd);return 0;
}

1、接口介绍

接下来,我首先带大家认识相关的接口。随后大家在来理解上述这两段代码!!

  • 最重要的当然是 open() ,通过对它的学习,我们将极大程度的理解有些知识

【解释说明】

参数

  • path:要打开的文件的路径字符串。
  • flags:打开文件的标志,可以使用一或多个以下标志的位或运算符 |

  第一个参数很好理解,对于第二个参数大家可能存在些疑惑我在这里重点讲讲关于这个标志的问题。

💨 首先,引入一个问题:OS是如何让用户给自己传递标志位的呢?

接下来,我给大家写个简单的 demo 样例帮助大家理解上述逻辑:

#include <stdio.h>#define ONE 0x1
#define TWO 0x2
#define THREE 0x4
#define FOUR 0x8
#define FIVE 0x10// 0000 0000 0000 0000 0000 0000 0000 0000
void Print(int flags)
{if(flags & ONE) printf("hello 1\n"); //充当不同的行为if(flags & TWO) printf("hello 2\n");if(flags & THREE) printf("hello 3\n");if(flags & FOUR) printf("hello 4\n");if(flags & FIVE) printf("hello 5\n");
}int main()
{printf("--------------------------\n");Print(ONE);printf("--------------------------\n");Print(TWO);printf("--------------------------\n");Print(FOUR);printf("--------------------------\n");Print(ONE|TWO);printf("--------------------------\n");Print(ONE|TWO|THREE);printf("--------------------------\n");Print(ONE|TWO|THREE|FOUR|FIVE);printf("--------------------------\n");return 0;
}

输出展示:

 【解释说明】

  1. 上述代码展示了使用位运算来模拟标志位。在这个示例中,每个标志位都表示一种不同的行为,当相应的位被设置时,相关的行为会执行;
  2. 首先,定义了一组宏来表示不同的标志位,每个标志位都对应一个唯一的二进制位。例如,ONE的二进制表示是:0000 0000 0000 0000 0000 0000 0000 0001TWO的二进制表示是:0000 0000 0000 0000 0000 0000 0000 0010,依此类推。
  3. 接下来,定义了一个Print函数,它接受一个整数参数flags,这个参数表示一组标志位的组合。在函数内部,使用位运算和按位与操作符&来检查每个标志位是否被设置。

有了上述认识,大家在返回去看 open() 函数中的 flags参数,我想就很明显了。当我们在man手册中往下面翻的时候就会看到如下内容:

  • 这一个个的选项就相当于宏,我们只需关于宏函数内部的意义即可!

2、代码示例

接下来,我们通过写代码的方式来进行理解!!

首先,有如下代码示例:

int main()
{int fd = open(LOG,O_WRONLY);if(fd == -1){printf("fd: %d, errno: %d, errstring: %s\n", fd, errno, strerror(errno));}else printf("fd: %d, errno: %d, errstring: %s\n", fd, errno, strerror(errno));close(fd);return 0;}

输出展示:

【解释说明】

  1. 上述代码的主要目的是打开一个文件并检查是否成功打开。如果打开失败,它将输出打开文件描述符(fd)、错误代码(errno)和错误字符串(strerror(errno));
  2. 然而,需要注意的是,因为开始并没有提供LOG这个文件,因此最后的输出肯定是发生报错。

解决方法就是在我们 open 的时候,再加上 【o_CREAT】这个标志:

输出展示:

然而,此时出现了一个奇怪的现象,我们通过查看得知 log.txt 文件的权限是处于乱码的情况:


因此,基于上述情况的出现。我们一般在用的时候一般不用 带两个参数的 open() ,而是用带三个参数的open() 函数

【解释说明】

  1. mode 是一个mode_t类型的参数,用于设置文件的权限;
  2. 它指定了文件的访问权限位,并且只有在使用O_CREAT标志创建文件时才会生效;
  3. 通常使用8进制表示权限位。例如,0644表示文件所有者具有读写权限,其他用户只有读权限。

基于上述情况,我们在后面加上相应的权限(我这里加的是0666):

输出展示: 

【解释说明】

  • 请注意,文件权限可能会受到操作系统的默认配置或其他因素的影响,即 umask;

  •  此时,系统默认的 umask 为2,因此在某些情况下,系统可能会对文件权限进行适当的修改,以使其符合操作系统的权限策略。

那么要如何保障这里的权限不受系统的影响呢?—— 我们可以自己设置

  • 此时,我们又需要引入一个新的函数:

接下来,我们对代码进行修改操作: 

输出展示:

【注意】

  • open 函数具体使用哪个,和具体应用场景相关,如目标文件不存在,需要open创建,则第三个参数表示创建文件的默认权限,否则,使用两个参数的open。

接下来,我们就需要往文件中写入数据了。在C++中,系统提供 write() 函数来进行写操作。

代码展示:

输出展示:


上述完成写入数据,接下来就是从文件中读出数据。在C++中,系统提供了 read() 函数

man手册查询:

代码展示:

输出展示:

【小结】

  • 有了上述这些认识,在回过头去看我给出的 读和写 的代码就容易了!

(三)总结

上面的 fopen fclose fread fwrite 都是C标准库当中的函数,我们称之为库函数(libc);


open close read write lseek 都属于系统提供的接口,称之为系统调用接口


回忆一下我们讲操作系统概念时,画的一张图:

  1. 根据上述图片,我们可以知道系统调用接口和库函数的关系,一目了然。
  2. 所以,可以认为,f#系列的函数,都是对系统调用的封装,方便二次开发。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/77589.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WebDAV之π-Disk派盘 + BubbleUPnP

BubbleUPnP是一款功能强大的Android播放器,支持UPnP/DLNA多屏互动。它可以将手机内容投屏到电视大屏上,与家人和朋友一起共享。此外,BubbleUPnP还提供了丰富的音乐和影视资源,您可以在线搜索并播放喜欢的内容。 以下是BubbleUPnP的一些主要特点: 1. 支持Chromecast和转码…

android java读写yaml文件

目录 申请读写权限&#xff1a; build.gradle中添加库引用&#xff1a; android java读写yaml文件 java修改yaml文件 YamlFile&#xff1a; 修改yaml文件方法2 Yaml&#xff1a; 删除值&#xff1a; 申请读写权限&#xff1a; <uses-permission android:name"and…

WebGL 绘制矩形

上一节绘制了圆点&#xff0c;调用的绘制方法如下&#xff1a;gl.drawArrays(gl.POINTS, 0, 1); 第一个参数明显是个枚举类型&#xff0c;肯定还有其他值&#xff0c;如下所示&#xff1a; POINTS 可视的点LINES 单独线段LINE_STRIP 线条LINE_LOOP 闭合线条TRIANGLES 单独三…

计算机网络篇之域名

计算机网络篇之域名 介绍 一个域名是一个由点分割的字符串序列&#xff0c;用于标识一组IP地址或互联网上的计算机&#xff0c;域名用于在因特网上标识和定位特定的网站或服务 组成 域名由两个主要部分组成&#xff1a;顶级域和二级域&#xff0c;顶级域是域名的最高级别&a…

Codeforces Round 895 (Div. 3) (A~G)

A. Two Vessels 题意&#xff1a;你有两个无限容量杯子A,B&#xff0c;分别装了a&#xff0c;b升的水&#xff0c;此外你还有一个容量为c的杯子C&#xff0c;你可以将一杯的水先倒入C中&#xff0c;再倒入另一个杯子&#xff0c;问你最少需要操作几次能使得A B杯的水量相同。 …

【题解】2596. 检查骑士巡视方案

题解&#xff1a; class Solution {int n,m;bool st[100][100];int flag;int dx[8]{-1,-2,-2,-1,1,2,2,1};int dy[8]{-2,-1,1,2,2,1,-1,-2}; public:bool checkValidGrid(vector<vector<int>>& grid) {m grid.size();n grid[0].size();dfs(grid,0,0,0);ret…

运行时链接

基本概念 运行时链接&#xff0c;是在程序运行时&#xff08;而非编译时或加载时&#xff09;将程序代码与其依赖的库代码进行链接的过程。动态链接在程序启动时或实际运行过程中通过API函数完成。这种方式的主要优点是它允许程序在运行时加载和卸载不同的库模块&#xff0c;从…

在Python中解决自定义类型比较的问题

1 问题原因 在Python编程中&#xff0c;当我们尝试对自定义类型进行比较时&#xff0c;可能会遇到这样的错误&#xff1a;TypeError: < not supported between instances of User and User 这个错误的原因是Python不知道如何对你的自定义类型进行比较。为了解决这个问题&a…

redisson常用api

redisson提供了很多对象类型的api&#xff0c;下面介绍下一些常用的对象api。 RBucket 可操作任何对象的api&#xff0c;前提是要确定好泛型&#xff0c;方法比较少。大小限制为512Mb。 RBucket<AnyObject> bucket redisson.getBucket("anyObject");bucket…

vue3中的吸顶导航交互实现 | VueUse插件

目的&#xff1a;浏览器上下滚动时&#xff0c;若距离顶部的滚动距离大于78px&#xff0c;吸顶导航显示&#xff0c;小于78px隐藏。使用vueuse插件中的useScroll方法​​​​​​​和动态类名控制进行实现 1. 安装 npm i vueuse/core 2. 获得滚动距离 项目中导入&#xff0…

@Resource 注入为null 的解决方法

Resource Resource可以用于注入对象 一般我们在编码中都会使用Resource来注入一个实例对象&#xff0c;但是特殊情况下可能会是null。 这个时候可以用SpringUtil.getBean()来手动获取 代码示例 private HbaseProperties hbaseProperties SpringUtil.getBean(HbasePropertie…

在python程序中用windows的icon

这个exe的弹窗功能会使用到一个ico文件&#xff0c;如图&#xff1a; 用软件GreenfishIconEditorProPortable或者使用在线软件将你需要的图片制作成windows的icon 用程序将ico文件生成文本文件 import base64picture_name "logo.ico" open_pic open("%s…

【100天精通Python】Day56:Python 数据分析_Pandas数据清洗和处理(删除填充插值,数据类型转换,去重,连接与合并)

目录 数据清洗和处理 1.处理缺失值 1.1 删除缺失值&#xff1a; 1.2 填充缺失值&#xff1a; 1.3 插值&#xff1a; 2 数据类型转换 2.1 数据类型转换 2.2 日期和时间的转换&#xff1a; 2.3 分类数据的转换&#xff1a; 2.4 自定义数据类型的转换&#xff1a; 3 数…

神经反馈设备使用感受2:采集Muse的EEG原始数据(转自知乎)

神经反馈设备使用感受2&#xff1a;采集Muse的EEG原始数据 转自知乎&#xff0c;内容很好&#xff0c;怕之后找不到 想了一下&#xff0c;单写一部分来介绍一下Muse在数据采集方面的操作。同时也解释一下我自己的EEG数据是从哪里采集的。 关于Muse EEG数据的精度&#xff0c;在…

vue2实现自定义主题webpack-theme-color-replacer

需求&#xff1a;根据element的自定义主题色&#xff0c;之后改变element的全局所有颜色&#xff0c;解决页面刷新后主题色失效问题&#xff0c;这个需要把颜色存入到浏览器的存储中&#xff0c;如果换个浏览器就得重新选择了哈&#xff0c;如果需要在不同的浏览器保持一致的主…

将AI融入到SEO中—基于Python的实现思路

在当今数字化时代&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;对于网站和在线业务的成功至关重要。然而&#xff0c;随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;我们可以利用它来提升SEO策略并取得更好的效果。本文将介绍如何通过使用Python编…

WordPress wp-file-manager 文件上传漏洞 CVE-2020-25213

1.漏洞复现 WordPress 6.2 插件&#xff1a;wp-file-manager 6.0&#xff0c;File Manager (advanced view) – WordPress plugin | WordPress.org &#xff08;https://wordpress.org/plugins/wp-file-manager/advanced/&#xff09; 复现 后台&#xff0c;安装、启动插件…

分布式系统第五讲:分布式事务及实现方案

分布式系统第五讲&#xff1a;分布式事务及实现方案 事务是一个程序执行单元&#xff0c;里面的所有操作要么全部执行成功&#xff0c;要么全部执行失败。而分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。本…

(二)程序语言设计基础

目录 1. 程序设计语言概述 1.1 基本概念 1.1.1 低级语言和高级语言 1.1.2 编译程序和解释程序 1.1.3 程序设计语言的定义 1.1.4 程序设计语言的分类 1.2 程序设计语言的基本成分 1.2.1 数据成分 1.2.2 运算成分 1.2.3 控制成分 1.2.4 传输成分 1.2.5 函数 2. 语言…

【LeetCode: 1462. 课程表 IV:拓扑排序+图+广度优先搜索】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…