【探索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等参数),然后再用鼠标在相应的层上添…...

wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...