【探索Linux】—— 强大的命令行工具 P.11(基础IO,文件操作)

阅读导航
- 前言
- 一、C语言的文件操作
- 二、C++的文件操作
- 三、Linux系统文件操作(I/O接口)
- 1. open()
- ⭕传入多个打开方式(按位或操作将不同的标志位组合在一起)
- 2. write()
- 3. read()
- 4. close()
- 5. lseek()
- 温馨提示
前言
前面我们讲了C语言的基础知识,也了解了一些数据结构,并且讲了有关C++的一些知识,也学习了一些Linux的基本操作,也了解并学习了有关Linux开发工具vim 、gcc/g++ 使用、yum工具以及git 命令行提交代码也相信大家都掌握的不错,上一篇文章我们了解了关于进程的地址空间,今天博主带大家了解一下 —— 基础IO,文件操作, 下面话不多说坐稳扶好咱们要开车了!!!😍
一、C语言的文件操作
⭕详细可见: C语言中的文件操作指南
C语言提供了标准库函数来进行文件操作,主要使用头文件 <stdio.h>。
以下是常见的文件操作函数及其用途
| 函数 | 作用 |
|---|---|
| FILE fopen(const char path, const char* mode) | 打开文件并返回指向文件的指针 |
| int fclose(FILE *stream) | 关闭文件 |
| int fputc(int c, FILE *stream) | 将一个字符写入文件 |
| int fgetc(FILE *stream) | 从文件中读取一个字符 |
| char *fgets(char *s, int size, FILE *stream) | 从文件中读取一行内容,并存储到字符串 s 中 |
| int fputs(const char *s, FILE *stream) | 将字符串 s 写入文件 |
| size_t fread(void *ptr, size_t size, size_t count, FILE *stream) | 从文件中读取二进制数据 |
| size_t fwrite(void *ptr, size_t size, size_t count, FILE *stream) | 向文件中写入二进制数据 |
| int fseek(FILE *stream, long offset, int whence) | 设置文件指针偏移量,用于定位读写位置 |
| long ftell(FILE *stream) | 返回当前文件指针的位置 |
| void rewind(FILE *stream) | 将文件指针重置到文件开头 |
| int feof(FILE *stream) | 检测是否到达文件末尾 |
其中,path 是文件路径,mode 表示打开文件的模式,可以是以下值之一:
| 模式 | 含义 |
|---|---|
| “r” | 只读模式,打开文件用于读取 |
| “w” | 写入模式,打开文件用于写入(清除文件中的原有内容) |
| “a” | 添加模式,打开文件用于追加数据 |
| “rb” | 二进制读取模式 |
| “wb” | 二进制写入模式 |
fputc 和 fgetc 函数用于单个字符的读写,fgets 和 fputs 函数用于字符串的读写。fread 和 fwrite 函数用于二进制数据的读写。
fseek 函数用于指定读写位置,ftell 函数用于获取当前文件指针的位置,rewind 函数用于将文件指针重置到文件开头。feof 函数用于检测是否到达文件末尾。
注意,在进行文件操作时,需要先打开文件,使用完毕后再关闭文件,否则可能导致资源泄漏或操作失败。
文件操作需要注意以下几点:
-
操作文件之前,需要先打开文件。在使用完文件后,必须关闭文件,释放资源。
-
文件指针可以用来读写文件中的内容。在进行读写操作时,需要根据文件指针指向的位置进行读写,可以使用
fseek函数来进行定位。 -
在进行写操作时,如果文件不存在,则会创建一个新的文件。如果文件已经存在,那么文件将被打开,并覆盖原有的内容。
-
在进行读操作时,需要判断是否已经到达文件末尾,通常使用
feof函数来进行判断。
二、C++的文件操作
C++提供了一组文件操作的标准库函数,可以用于打开、读取、写入和关闭文件。下面是一些常用的文件操作函数的介绍:
- 打开文件:
可以使用std::ifstream和std::ofstream来打开输入和输出文件流。例如:
#include <fstream>std::ifstream inFile("input.txt"); // 打开输入文件
std::ofstream outFile("output.txt"); // 打开输出文件
- 读取文件内容:
可以使用>>运算符从文件中读取数据。例如:
int num;
inFile >> num; // 从输入文件中读取一个整数到变量num中
也可以使用getline函数逐行读取文件内容。例如:
std::string line;
while (std::getline(inFile, line)) {// 处理每一行的内容
}
- 写入文件内容:
可以使用<<运算符将数据写入文件。例如:
int num = 42;
outFile << "The answer is: " << num << std::endl; // 将内容写入输出文件
- 关闭文件:
在完成文件的读写操作后,要记得关闭文件。可以使用close函数关闭文件流。例如:
inFile.close(); // 关闭输入文件
outFile.close(); // 关闭输出文件
这些只是文件操作中的一部分函数和用法,C++还提供了更多高级的文件处理功能,如文件定位、异常处理等。如果需要更详细的信息,建议参考C++的标准库文档或其他相关书籍。
三、Linux系统文件操作(I/O接口)
1. open()
open()是一个系统调用函数,用于打开文件或创建文件,可以在C语言、C++等编程语言中使用。该函数的声明如下:
#include <fcntl.h>
int open(const char *pathname, int flags, mode_t mode);
pathname参数表示要打开的文件路径,可以是绝对路径或相对路径;
flags参数表示打开文件时的访问方式,可能的取值有:
- O_RDONLY: 只读模式,打开文件后只能读取,无法写入。
- O_WRONLY: 只写模式,打开文件后只能写入,无法读取。
- O_RDWR: 读写模式,打开文件后既可以读取也可以写入。
- O_APPEND: 写入时追加到文件末尾。
- O_CREAT: 如果文件不存在,则创建文件。
mode参数表示文件权限(即文件所有者、所有组和其他用户的访问权限),通常使用八进制数表示。当O_CREAT标志被设置时,mode参数才有效。
open()函数返回一个非负整数作为文件描述符,代表新文件的访问点。如果发生错误,则返回-1,并设置全局变量errno来指示错误类型。
在Linux系统中,open()是底层文件操作中最为基础和最常用的函数之一。通过它,我们可以实现文件的读取、写入、修改、删除等操作。了解这个函数的用法和参数对我们进行文件操作的开发和调试都非常有帮助。
⭕传入多个打开方式(按位或操作将不同的标志位组合在一起)
按位或操作是一种位运算操作,其原理是对两个操作数的每一个二进制位进行逻辑或(OR)运算。具体来说,如果两个操作数中的某一位至少有一个为1,则结果的相应位将置为1;否则,结果的相应位将置为0。
在使用按位或操作符|将不同的标志位组合在一起时,实际上是将各个标志位的二进制表示进行按位或运算,从而得到一个组合了多个标志的结果值。
例如,假设有两个标志位常量:
#define FLAG_A 0b00000001 // 二进制表示的标志位A,第1位为1
#define FLAG_B 0b00000010 // 二进制表示的标志位B,第2位为1
当执行按位或操作FLAG_A | FLAG_B时,按位或操作会将二进制表示中的对应位进行按位或运算:
00000001 (FLAG_A)| 00000010 (FLAG_B)-------------00000011 (结果:FLAG_A | FLAG_B)
由于标志位A和标志位B的二进制表示在第1位和第2位都为1,因此按位或操作的结果中,第1位和第2位都被置为1。
这样,通过不断使用按位或操作|将多个标志位进行组合,可以将多个标志位的信息合并在一起,得到一个表示多个标志的结果值。
要传入多个打开方式,可以通过按位或(bitwise OR)操作将不同的标志位组合在一起。使用按位或操作符|可以将不同的标志位进行逻辑或运算。
下面的代码,展示了如何传入多个打开方式:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main() {int fileDescriptor;char buffer[100];// 打开文件,以读写和追加方式打开fileDescriptor = open("example.txt", O_RDWR | O_APPEND);if (fileDescriptor == -1) {perror("打开文件失败");exit(EXIT_FAILURE);}// 读取文件内容ssize_t bytesRead = read(fileDescriptor, buffer, sizeof(buffer));if (bytesRead == -1) {perror("读取文件失败");exit(EXIT_FAILURE);}// 输出文件内容write(STDOUT_FILENO, buffer, bytesRead);// 关闭文件close(fileDescriptor);return 0;
}
上述代码中,使用了按位或操作符|将O_RDWR和O_APPEND两个打开标志位进行了逻辑或运算,表示同时以读写和追加方式打开文件。
2. write()
write()函数是Linux/Unix系统中一个用于向文件或文件描述符写入数据的系统调用函数。其声明如下:
#include <unistd.h>ssize_t write(int fd, const void *buf, size_t count);
其中,fd参数是要写入的文件描述符,buf参数是指向将要写入的数据缓冲区的指针,count参数是要写入的数据字节数。
write()函数的常见用法如下:
#include <unistd.h>
#include <fcntl.h>int fd = open("myfile", O_WRONLY); // 打开文件
char *buf = "Hello, World!"; // 待写入的数据
ssize_t n = write(fd, buf, strlen(buf)); // 写入数据
close(fd); // 关闭文件
该程序打开名为"myfile"的文件,并将字符串"Hello, World!"写入该文件中,最后关闭文件。
write()函数的返回值为成功写入的字节数,如果发生错误则返回-1。
3. read()
read()函数是Linux/Unix系统中一个用于从文件或文件描述符读取数据的系统调用函数。其声明如下:
#include <unistd.h>ssize_t read(int fd, void *buf, size_t count);
其中,fd参数是要读取的文件描述符,buf参数是指向读取数据缓冲区的指针,count参数是要读取的数据字节数。
read()函数的常见用法如下:
#include <unistd.h>
#include <fcntl.h>int fd = open("myfile", O_RDONLY); // 打开文件
char buf[1024]; // 缓冲区
ssize_t n = read(fd, buf, sizeof(buf)); // 读取数据到缓冲区
close(fd); // 关闭文件
该程序打开名为"myfile"的文件,并从该文件中读取数据到缓冲区中,最后关闭文件。
read()函数的返回值为实际读取的字节数,如果到达文件末尾则返回0,如果发生错误则返回-1。
4. close()
close()函数是一个系统调用函数,用于关闭先前打开的文件描述符。它会释放与该文件描述符相关的所有系统资源。
其函数原型如下:
#include <unistd.h>int close(int fd);
其中,fd是要关闭的文件描述符。
close()函数的常见用法如下:
#include <unistd.h>
#include <fcntl.h>int fd = open("myfile", O_RDONLY); // 打开文件
// 使用文件描述符进行读取或写入操作
close(fd); // 关闭文件
在上述示例中,首先使用open()函数打开了名为"myfile"的文件,并获得了文件描述符fd。在完成读取或写入操作后,可以使用close()函数关闭文件描述符fd,以释放与该文件描述符相关的系统资源。
在关闭文件时,close()函数会执行一些清理操作,例如刷新缓冲区、释放资源等。成功关闭文件时,close()函数返回0;如果发生错误,返回-1,此时可以通过检查全局变量errno来获取具体的错误信息。
需要注意的是,不正确地使用文件描述符,或者未正确关闭文件描述符,可能会导致资源泄漏或其他问题。因此,在不需要使用文件描述符时,及时调用close()函数关闭文件是一个良好的编程习惯。
5. lseek()
lseek()函数是一个系统调用函数,用于在文件中移动文件读写位置指针。它可以用于改变文件当前的偏移量。
其函数原型如下:
#include <unistd.h>off_t lseek(int fd, off_t offset, int whence);
其中,fd是要操作的文件描述符;offset是相对于whence参数指定位置的偏移量;whence参数指定了计算偏移量的方式。
lseek()函数的常见用法如下:
#include <unistd.h>
#include <fcntl.h>int fd = open("myfile", O_RDONLY); // 打开文件off_t new_offset = lseek(fd, 0, SEEK_END); // 将文件读写位置指针设置到文件末尾
// 进行读取或写入操作close(fd); // 关闭文件
在上述示例中,首先使用open()函数打开了名为"myfile"的文件,并获得了文件描述符fd。然后,使用lseek()函数将文件读写位置指针设置到文件末尾(通过将offset参数设置为0和whence参数设置为SEEK_END)。这样,我们就可以在末尾进行读取或写入操作。
通过使用不同的whence参数,可以实现不同的偏移量计算方式,常见的参数包括:
- SEEK_SET:将位置指针设置为相对于文件开始位置的偏移量。
- SEEK_CUR:将位置指针设置为相对于当前位置的偏移量。
- SEEK_END:将位置指针设置为相对于文件末尾的偏移量。
lseek()函数返回新的文件偏移量,如果发生错误,则返回-1,并将错误信息存储在全局变量errno中。
温馨提示
感谢您对博主文章的关注与支持!如果您喜欢这篇文章,可以点赞、评论和分享给您的同学,这将对我提供巨大的鼓励和支持。另外,我计划在未来的更新中持续探讨与本文相关的内容。我会为您带来更多关于Linux以及C++编程技术问题的深入解析、应用案例和趣味玩法等。如果感兴趣的话可以关注博主的更新,不要错过任何精彩内容!
再次感谢您的支持和关注。我们期待与您建立更紧密的互动,共同探索Linux、C++、算法和编程的奥秘。祝您生活愉快,排便顺畅!

相关文章:
【探索Linux】—— 强大的命令行工具 P.11(基础IO,文件操作)
阅读导航 前言一、C语言的文件操作二、C的文件操作三、Linux系统文件操作(I/O接口)1. open()⭕传入多个打开方式(按位或操作将不同的标志位组合在一起) 2. write()3. read()4. close()5. lseek() 温馨提示 前言 前面我们讲了C语言…...
前端练习项目(附带页面psd图片及react源代码)
一、前言 相信很多学完前端的小伙伴都想找个前端项目练练手,检测自己的学习成果。但是现在很多项目市面上都烂大街了。今天给大家推荐一个全新的项目——电子校园 项目位置:https://github.com/v5201314/eSchool 二、项目介绍(部分页面展示)ÿ…...
【从零开始学习Redis | 第三篇】在Java中操作Redis
前言: 本文算是一期番外,介绍一下如何在Java中使用Reids ,而其实基于Java我们有很多的开源框架可以用来操作redis,而我们今天选择介绍的是其中比较常用的一款:Spring Data Redis 目录 前言: Spring Data…...
vim、gcc/g++、make/Makefile、yum、gdb
vim、gcc/g、make/Makefile、yum、gdb 一、Linux编辑器vim1、简介2、三种模式的概念(1)正常/普通/命令模式(Normal mode)(2)插入模式(Insert mode)(3)末行/底行模式(last line mode) 3、三种模式的切换4、正…...
2022最新版-李宏毅机器学习深度学习课程-P13 局部最小值与鞍点
一、优化失败的原因 局部最小值?鞍点? 二、数学推导分析 用泰勒公式展开 一项与梯度(L的一阶导)有关,一项与海赛矩阵(L的二阶导)有关 海瑟矩阵 VTHV通过海瑟矩阵的性质可以转为判断H是否是正…...
ARM架构的基本知识
ARM两种授权 体系结构授权, 一种硬件规范, 用来约定指令集, 芯片内部体系结构(内存管理, 高速缓存管理), 只约定每一条指令的格式, 行为规范, 参数, 客户根据这个规范自行设计与之兼容的处理器处理IP授权, ARM公司根据某个版本的体系结构设计处理器, 再把处理器设计方案授权给…...
网络安全(黑客技术)——如何高效自学
前言 前几天发布了一篇 网络安全(黑客)自学 没想到收到了许多人的私信想要学习网安黑客技术!却不知道从哪里开始学起!怎么学?如何学? 今天给大家分享一下,很多人上来就说想学习黑客,…...
云原生场景下高可用架构的最佳实践
作者:刘佳旭(花名:佳旭),阿里云容器服务技术专家 引言 随着云原生技术的快速发展以及在企业 IT 领域的深入应用,云原生场景下的高可用架构,对于企业服务的可用性、稳定性、安全性越发重要。通…...
图论-最短路径算法-弗洛伊德算法与迪杰斯特拉算法
弗洛伊德算法: 弗洛伊德算法本质是动态规划,通过添加点进如可选择的点组成的集合的同时更新所有点之间的距离,从而得到每两个点之间的最短距离。 初始化: 创建一个二维数组 dist,其中 dist[i][j] 表示从节点 i 到节点…...
[23] IPDreamer: Appearance-Controllable 3D Object Generation with Image Prompts
pdf Text-to-3D任务中,对3D模型外观的控制不强,本文提出IPDreamer来解决该问题。在NeRF Training阶段,IPDreamer根据文本用ControlNet生成参考图,并将参考图作为Zero 1-to-3的控制条件,用基于Zero 1-to-3的SDS损失生成…...
深入理解React中的useEffect钩子函数
引言: React是一种流行的JavaScript库,它通过组件化和声明式编程的方式简化了前端开发。在React中,一个核心概念是组件的生命周期,其中包含了许多钩子函数,用于管理组件的不同阶段。其中之一就是useEffect钩子函数&…...
数字化时代的财务管理:挑战与机遇
导语:随着数字化技术的不断发展,财务管理正面临着前所未有的挑战和机遇。数字化不仅改变了财务数据的收集、处理和分析方式,还为财务决策提供了更多的依据和方向。本文将探讨数字化时代财务管理的新特点,以及如何利用数字化技术提…...
网络通信协议-HTTP、WebSocket、MQTT的比较与应用
在今天的数字化世界中,各种通信协议起着关键的作用,以确保信息的传递和交换。HTTP、WebSocket 和 MQTT 是三种常用的网络通信协议,它们各自适用于不同的应用场景。本文将比较这三种协议,并探讨它们的主要应用领域。 HTTPÿ…...
【深度学习】深度学习实验四——循环神经网络(RNN)、dataloader、长短期记忆网络(LSTM)、门控循环单元(GRU)、超参数对比
一、实验内容 实验内容包含要进行什么实验,实验的目的是什么,实验用到的算法及其原理的简单介绍。 1.1 循环神经网络 (1)理解序列数据处理方法,补全面向对象编程中的缺失代码,并使用torch自带数据工具将数据封装为dataloader。 (2)分别采用手动方式以及调用接口方式…...
DB2分区表详解
一、分区表基本概念 当表中的数据量不断增大,查询数据的速度就会变慢,应用程序的性能就会下降,这时就应该考虑对表进行分区。分区后的表称为分区表。 表进行分区后,逻辑上表仍然是一张完整的表,只是将表中的数据在物理上存放到多个“表空间”(物理文件上),这样查询数据时…...
基本地址变换机构
基本地址变换机构:用于实现逻辑地址到物理地址转换的一组硬件机构。 关于页号页表的定义,放个本人的传送门 1.页表寄存器 基本地址变换机构可以借助进程的页表将逻辑地址转换为物理地址。 1.作用 通常会在系统中设置一个页表寄存器(PTR&…...
以单颗CMOS摄像头重构三维场景,维悟光子发布单目红外3D成像模组
维悟光子近期发布全新单目红外3D成像模组,现可提供下游用户进行测试导入。通过结合微纳光学元件编码和人工智能算法解码,维悟光子单目红外3D成像模组采用单颗摄像头,通过单帧拍摄,可同时获取像素级配准的3D点云和红外图像信息,可被应用于机器人、生物识别等广阔领域。 市场…...
Jinja2模板注入 | python模板注入特殊属性 / 对象讲解
在进行模板利用的时候需要使用特殊的属性和对象进行利用,这里对这些特殊属性及方法进行讲解 以下实验输出python3版本为 3.10.4, python2版本为 2.7.13 特殊属性 __class__ 类实例上使用,它用于获取该实例对应的类__base__ 用于获取父类__mr…...
一致性公式证明
首先,假设存在两个不同的聚类假设 f 1 f^1 f1和 f 2 f^2 f2,它们在两个视角上的聚类结果分别为 y 1 ∈ { − 1 , 1 } n y^1\in\{-1,1\}^n y1∈{−1,1}n和 y 2 ∈ { − 1 , 1 } n y^2\in\{-1,1\}^n y2∈{−1,1}n。 证明一致性不等式: …...
allegro中shape的一些基本操作(一)——添加和修改shape
添加shape 简单添加shape的方式有3种,如下图所示 点击选择相应的shape模式后可以在option面板中设置相应的shape参数(这里不做过多介绍,里面可以设置shape的大小、静态或动态shape等参数),然后再用鼠标在相应的层上添…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...
保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...
鸿蒙(HarmonyOS5)实现跳一跳小游戏
下面我将介绍如何使用鸿蒙的ArkUI框架,实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...
