【Linux】基础IO——系统文件IO

news2025/3/1 20:53:17

我之前是讲过c语言的文件操作的,但是说实话我压根就不知道它在干什么,后面c语言/c++,数据结构的学习过程中也没用过文件操作,今天我们就来会会这个文件操作 

1.回顾c语言文件接口

1.1.fopen

  1. r :只读模式打开,文件流指针指向文件的起始位置
  2. r+:可读可写方式打开,文件流指针指向文件的起始位置
  3. w:只写模式打开,被打开文件若存在,则截断文件(清空文件内容),若不存在,创建该文件
  4. w+:可读可写模式打开,,被打开文件若存在,则截断文件(清空文件内容),若不存在,创建该文件
  5. a:追加写。若文件存在,文件流指针指向文件的末尾进行写。若不存在,创建文件
  6. a+:可以读也可以 追加写。文件存在,读的位置被初始化到文件头,追加写的时候依旧是在文件末尾追加 ,文件不存在,创建该文件

我们来实验一下

1.1.1.r选项

#include <stdio.h>
int main()
{
	FILE* fp = fopen("log.txt", "r");
	if (fp == NULL){
		perror("fopen");
		return 1;
	}
	char buffer[64];
	for (int i = 0; i < 5; i++){
		fgets(buffer, sizeof(buffer), fp);//读取
		printf("%s", buffer);
	}
	fclose(fp);
	return 0;
}

 我们发现只是单纯的读取而已

1.1.2.w选项

#include <stdio.h>
int main()
{
	FILE* fp = fopen("log.txt", "w");
	if (fp == NULL){
		perror("fopen");
		return 1;
	}
	int count = 5;
	while (count){
		fputs("hello world\n", fp);//向文件中写入
		count--;
	}
	fclose(fp);
	return 0;
}

运行后,当前路径下会生成log.txt文件,并会写入内容。 

当我们以“w”的方式打开文件代表写入,此时他会清空文件,再帮我们写入。 

1.1.3.其他

当我们把选项换成“a”,这就代表append追加,这就不会清空文件。 

再命令行中的“>”符号,这叫做输出重定向。 

可以看到之前的内容就没有了,变成了重定向的内容,他也是类似于“w”的方式。

再来看一下“r”选项打开文件,可以读取文件中的数据到缓冲区中,并输出到屏幕上。

int main()
{
    FILE* fp = fopen("log.txt", "r");
    if (fp == NULL)
    {
        perror("fopen");
        return 1;
    }
    // 文件操作
 
    char line[64];// 缓冲区
    // fgets是C语言的接口,按行读取,自动在字符结尾添加\0
    while (fgets(line, sizeof(line), fp) != NULL)
    {
        fprintf(stdout, "%s", line);
    }
 
    fclose(fp);
 
    return 0;
}

加入命令行参数后就变成了类似cat命令的操作,也可以给简易的shell添加上这个功能。

int main(int argc, char* argv[])
{
    if (argc != 2)
    {
        printf("请输入两个参数:程序+文件名\n");
        exit(1);
    }
    FILE* fp = fopen(argv[1], "r");
    if (fp == NULL)
    {
        perror("fopen");
        return 1;
    }
    // 文件操作
 
    char line[64];// 缓冲区
    // fgets是C语言的接口,按行读取,自动在字符结尾添加\0
    while (fgets(line, sizeof(line), fp) != NULL)
    {
        fprintf(stdout, "%s", line);
    }
 
    fclose(fp);
 
    return 0;
}

 

2.默认打开的三个流(stdin,stdout,stderr)

Linux下一切皆文件,显示器和键盘也可以看作文件。

        我们能看到显示器上的数据,是因为我们向显示器写入了数据,电脑能获取我们键盘上的字符,是电脑从“键盘文件” 读取了数据。

        为什么我们向“显示器文件”写入数据以及从“键盘文件”读取数据前,不需要进行打开“显示器文件”和“键盘文件”的相应操作?

        需要注意的是,打开文件一定是进程运行的时候打开的,而任何进程在运行的时候都会默认打开三个输入输出流,即标准输入流、标准输出流以及标准错误流,对应到C语言当中就是stdin、stdout以及stderr。
        其中,标准输入流对应的设备就是键盘,标准输出流和标准错误流对应的设备都是显示器。

查看man手册我们就可以发现,stdin、stdout以及stderr这三个家伙实际上都是FILE*类型的。

stdin默认为键盘,stdout和stderr默认为显示器,这些都是硬件,但在Linux下,一切皆文件,所以这三个的类型都是FILE*,这是个指针,FILE其实是C标准库提供的结构体 

        当我们的程序被运行起来时,操作系统就会默认使用C语言的相关接口将这三个输入输出流打开。

        注意: 不止是C语言当中有标准输入流、标准输出流和标准错误流,C++当中也有对应的cin、cout和cerr,其他所有语言当中都有类似的概念。实际上这种特性并不是某种语言所特有的,而是由操作系统所支持的。

3.系统文件IO

        通过之前的学习,这些文件操作最终都是访问硬件(显示器、键盘、磁盘)众所周知,OS是硬件的管理者。所有语言上对“文件”的操作,都必须贯穿操作系统。然而OS不相信任何人,访问操作系统,就必须要通过系统接口!!

open/fclose,fread/fwrite,fputs/fgets,fgets/fputs 等库函数一定需要使用OS提供的系统调用接口,接下来我们就来学习文件的系统调用接口,才能做到万变不离其宗!!

我们在Linux平台下运行C代码时,C库函数就是对Linux系统调用接口进行的封装,在Windows平台下运行C代码时,C库函数就是对Windows系统调用接口进行的封装,这样做使得语言有了跨平台性,也方便进行二次开发。

 3.1.open

3.1.1.参数pathname

open的第一个参数:pathname

open的第一个参数表示打开或者创建目标文件。

在这里要注意的是:

  • 1.如果以路径的形式给出那么当需要创建文件的时候,会在你提供的这个路径下创建。
  • 2.如果只给了文件名,那么会在当前路径下创建(当前路径上面以及提过注意他的含义)。

3.1.2.参数flags 

open的第二个参数:flags

open的第二个参数表示文件打开的方式。常用选项有如下几种:

  • O_RDONLY:只读打开
  • O_WRONLY:只写打开
  • O_RDWR:读,写打开 

上面三个常量,必须指定一个且只能指定一个

  • O_CREAT:若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
  • O_APPEND:追加写
  • O_TRUNC:清空文件

我们在打开文件时可以使用多个选项中间以|隔开。

        举个例子:我们想要以只写的方式打开一个文件如果文件不存在就创建O_WRONLY|O_CREAT。

那flags到底是个什么呢?

        其实它就是一个整数,一个整数有32个比特位,将每一个比特位做为某一个选项,在对应的函数内看那一位是否为1,来判断我们是否传入了这个选项.那么也就意味着O_WRONLY对应的是32个比特位中只有一位是1的整数,到底是不是这样的了?

        下面我们使用vim打开/usr/include/asm-generic/fcntl.h这个目录下的文件看一看:

 我们发现这些宏定义选项的共同点就是,它们的二进制序列当中有且只有一个比特位是1 (O_RDONLY)选项的二进制序列为全0,表示O_RDONLY选项为默认选项)。

        而在open函数中使用特定的数字进行判断然后只写具体的功能。

那第二个参数flags(int)是怎么实现模式的叠加的?为什么要把模式|在一起呢?

 这是一种用户层给内核传递标志位的常用做法。
        int有32个比特位,不重复的一个bit,就可以表示不同状态,就可以传递多个标志位且位运算效率较高。

        这些O_RDONLY、O_WRONLY、O_RDWR都是只有一个比特位是1的宏,并且相互不重复,这样|在一起,就能传递多个标志位

 下面用一段代码演示一下。

// 用int中不同的bit位就可以标识一种值
#define ONE 0x1   // 0000 0001
#define TWO 0x2   // 0000 0010
#define THREE 0x4 // 0000 0100
 
void Print(int flags)
{
    if (flags & ONE)
        printf("one\n");
    if (flags & TWO)
        printf("two\n");
    if (flags & THREE)
        printf("three\n");
}
 
int main()
{
    Print(ONE | TWO); // 0001 | 0010 -> 0011
    printf("--------------\n");
    Print(ONE | TWO | THREE); // 0001 | 0010 | 0100 -> 0111
    return 0;
}

相信看到这里,你也就明白了为什么模式可以通过|来叠加的?

当然,你也就明白了为什么下面只能三选一

3.1.3.参数mode

(注意当不创建文件时,第三个参数可以不用填)

open的第三个参数:第三个参数为设置创建文件的权限。

在linux中文件是有权限的,当以只写方式打开文件,文件如果不存在需要创建但是创建时我们需要设置文件的权限。

3.1.4.返回值 

open的返回值是指我们打开文件的这个文件描述符,打开失败返回-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后面递增的。

        实际上这里所谓的文件描述符本质上是一个指针数组的下标,指针数组当中的每一个指针都指向一个被打开文件的文件信息通过对应文件的文件描述符就可以找到对应的文件信息。

        当使用open函数打开文件成功时数组当中的指针个数增加,然后将该指针在数组当中的下标进行返回,而当文件打开失败时直接返回-1,因此,成功打开多个文件时所获得的文件描述符就是连续且递增的。

        而Linux进程默认情况下会有3个缺省打开的文件描述符,分别就是标准输入0、标准输出1、标准错误2,这就是为什么成功打开文件时所得到的文件描述符是从3开始进程分配的。

3.1.5.使用示例

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
 
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
 
int main()
{
    int fd = open("log.txt", O_WRONLY);//以只读方式打开文件
    if (fd < 0)
    {
        perror("open");
        exit(1);
    }
    
    // 打开成功
   printf("fd: %d\n", fd); 
 
    return 0;
}

 

我们发现,没有log.txt的情况下,只读模式情况下打印了这个

我们换换只写模式

 

还是不会自己创建啊,看来这个写和c语言的w模式还是有点区别的

我们往上看第二个参数,发现创建文件还是要加上一个选项的

我们修改一下代码

       

通过这次实验,完美发现c语言的那些r,w等模式不就是open的这些模式的混合版本嘛!!

事实上确实是这样,不只是c语言,包括c++,python等都是如此

   这次是创建成功了,但是它的权限好奇怪啊

        我们不要忘了open它有第三个参数mode,这就是创建文件的访问权限,想要给他的权限设置为0666,就要把它传入,当然也要注意umask,系统的默认umask是0002,所以还要在一开始设置当前进程的umask,如何设置也可以用接口。

 

这个权限非常完美了吧!!!

3.2.close

     使用close函数时传入需要关闭文件的文件描述符即可,若关闭文件成功则返回0,若关闭文件失败则返回-1。

 3.3.write

系统接口中使用write函数向文件写入信息,write函数的函数原型如下:

write函数,将buf位置开始向后count字节的数据写入文件描述符为fd的文件当中。

写入成功返回写入数据的字节个数,失败返回-1.

 我们来使用一下

又一次写入时,我们发现:

O_TRUNC: 打开文件的时候直接清空文件

O_TRUNC:
    如果文件已经存在并且是一个常规文件,并且开放模式允许写入(即是0_RDNRor O_MwRONLY),那么它将被截断为长度为0(也就是清空文件)

 这样就可以变成C语言中fopen的w选项。

这样a选项也就好说了,选项变成O_APPEND就行了。 

O_APPEND: 追加文件

int fd = open("log.txt", O_WRONLY | O_CREAT | O_APPEND, 0666);

注意注意:写入文件的过程中,不需要写入\0

        因为\0是C语言层面上规定字符串的结束标志,而写入文件关心的是字符串的内容,文件和语言不要搞混了 

3.4.read

  • 第一个参数是文件对应的文件描述符
  • 第二个参数是读取的内容放到这里
  • 第三个参数读取几个字节,返回值为实际读取的字节数读取失败返回-1. 

读文件的前提:文件已经存在,不涉及创建及权限的问题,那么用两个参数的open打开文件即可 

未完待续…… 

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

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

相关文章

多类型图像OCR:基于Dify的多模态Agent实现

大模型相关目录 大模型&#xff0c;包括部署微调prompt/Agent应用开发、知识库增强、数据库增强、知识图谱增强、自然语言处理、多模态等大模型应用开发内容 从0起步&#xff0c;扬帆起航。 大模型应用向开发路径&#xff1a;AI代理工作流大模型应用开发实用开源项目汇总大模…

用Python处理Excel的资源

用Python处理Excel的资源 python-excel 读写Excel文件 openpyxl openpyx文档l 读写Excel2010文件&#xff08;即xlsx&#xff09; openpyxl示例&#xff1a; from openpyxl import Workbook wb Workbook()# 获取active worksheet ws wb.active# 给单元格赋值 ws[A1] 4…

创邻科技张晨:期待解锁图技术在供应链中的关联力

近日&#xff0c;创邻科技创始人兼CEO张晨博士受浙江省首席信息官协会邀请&#xff0c;参加数字化转型与企业出海研讨会。 此次研讨会旨在深入探讨数字经济时代下&#xff0c;企业如何有效应对成本提升与环境变化所带来的挑战&#xff0c;通过数字化转型实现提效增益&#xff…

生命在于学习——Python人工智能原理(3.3)

三、深度学习 4、激活函数 激活函数的主要作用是对神经元获得的输入进行非线性变换&#xff0c;以此反映神经元的非线性特性。常见的激活函数有线性激活函数、符号激活函数、Sigmod激活函数、双曲正切激活函数、高斯激活函数、ReLU激活函数。 &#xff08;1&#xff09;线性…

推流工具OBS的下载使用

一、下载安装 OBS&#xff0c;windows版本官网下载地址 二、推流步骤 安装好之后&#xff0c;打开软件 1、右下角&#xff0c;打开设置 2、输入推流地址&#xff0c;一般为rtmp格式开头的推流地址 输入完成后&#xff0c;应用并确定关闭窗口 3、“来源”里面新建媒体源、新…

RK3566调试VI5301

VI5301是南京芯视界推出的一款直接飞行时间&#xff08;dToF&#xff09;传感器&#xff0c;与ST的VL53L0x兼容。 一、开发平台 系统&#xff1a;linux 4.19(buidroot) 二、驱动移植 解压厂家提供的驱动文件&#xff1a;VI5301_Linux_General_M40_V202&#xff0c;目录结构…

4、视觉里程计:特征点法、直接法和半直接法

先说一下我自己的总体理解&#xff1a; 特征点法&#xff0c;基于最小化重投影误。 提取特征点&#xff0c;计算描述子&#xff0c;匹配&#xff0c;运动估计。 计算描述子和匹配部分可以用光流法跟踪替代 总体上先知道像素之间的关系&#xff0c;在估计运动&#xff08;最…

【C语言】一篇文章带你深度理解函数

目录 1. 函数的概念 2. 库函数 2.1 标准库和头文件 2.2 库函数的使用方法 2.2.1 举例 sqrt 2.2.2 库函数文档的一般格式 3. 自定义函数 3.1 函数的语法形式 3.2 函数的举例 4. 形参和实参 4.1 实参 4.2 形参 4.3 实参和形参的关系 5. …

【区块链】记账的千年演化:从泥板到区块链

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 记账的千年演化&#xff1a;从泥板到区块链引言一、古代记账&#xff1a;泥板与…

ComfyUI-全民舞王-MusePose

musepose-demo 项目介绍 https://github.com/TMElyralab/MusePose发布的模型能够根据给定的姿势序列&#xff0c;生成参考图中人物的舞蹈视频&#xff0c;结果质量超越了同一主题中几乎所有当前开源的模型。发布pose align算法&#xff0c;以便用户可以将任意舞蹈视频与任意参…

基于Matlab的纸币币值检测系统设计(GUI界面) 【含Matlab源码 MX_004期】

简介&#xff1a; 基于Matlab的纸币币值检测系统是一种利用数字图像处理技术来自动识别和鉴别纸币面额的系统。 图像获取&#xff1a;获取纸币的图像。 预处理&#xff1a;对获取到的图像进行预处理&#xff0c;包括去噪、灰度化、边缘检测等操作&#xff0c;以便后续的处理。…

电脑找不到vcruntime140_1.dll的原因分析及5种解决方法分享

电脑已经成为我们生活和工作中不可或缺的工具。然而&#xff0c;在使用电脑的过程中&#xff0c;我们常常会遇到一些常见的问题&#xff0c;其中之一就是电脑显示vcruntime140_1.dll丢失。那么&#xff0c;这个问题是怎么回事呢&#xff1f;又有哪些解决方法呢&#xff1f;如何…

首期“软件企业 AI 开发提效实战营”成功举办

人工智能是国家战略的重要组成部分&#xff0c;是未来国际竞争的焦点和经济发展的新引擎。随着人工智能科技的飞速发展&#xff0c;软件企业如何借助 AI 工具辅助编程&#xff0c;提升开发效率&#xff0c;成为业界关注的焦点。此前&#xff0c;浙江省软件行业协会携手阿里云成…

GitCode热门开源项目推荐:Spider网络爬虫框架

在数字化高速发展时代&#xff0c;数据已成为企业决策和个人研究的重要资源。网络爬虫作为一种强大的数据采集工具受到了广泛的关注和应用。在GitCode这一优秀的开源平台上&#xff0c;Spider网络爬虫框架凭借其简洁、高效和易用性&#xff0c;成为了众多开发者的首选。 一、系…

网络编程---Java飞机大战联机

解析服务器端代码 代码是放在app/lib下的src下的main/java&#xff0c;而与之前放在app/src/main下路径不同 Main函数 Main函数里只放着创建MyServer类的一行 public static void main(String args[]){new MyServer();} MyServer构造函数 1.获取本机IP地址 //获取本机IP地…

上网行为管理的作用是什么?有哪些上网行为管理软件?

上网行为管理在现代企业及家庭环境中扮演着至关重要的角色&#xff0c;其作用不仅限于提升网络安全性&#xff0c;还涉及保护企业信息安全、提高员工工作效率等多个方面。以下将详细阐述上网行为管理的作用&#xff0c;并介绍几款主流的上网行为管理软件。 一、上网行为管理的作…

CANoe连接Option Scope使用方法

系列文章目录 文章目录 系列文章目录前言一、前提条件二、CANoe配置三、PicoScope接线四、CANoe捕捉报文五、眼图功能前言 本文档主要介绍如何使用CANoe Option .Scope捕获CAN总线上的物理波形,并利用眼图进行分析。 一、前提条件 使用CANoe Option .Scope,需要具备以下条件…

Folx软件下载及安装教程

简介&#xff1a; Folx Pro是一款适合Mac的专业下载工具也是一款BT下载器&#xff0c;Folx中文版有一个支持Retina显示的现代界面&#xff0c;提供独特的系统排序、存储下载内容与预览下载文件。Folx中文官网提供Folx教程、激活码、下载。 安 装 包 获 取 地 址&#xff1a; …

c->c++(一):部分KeyWord

本文主要探讨c相关关键字的使用。 char char默认是unsigned/signed取决平台,wchar_t宽字符:用于Unicode编码(超过一个字节),用wcin和wcout输入输出,字符串为wstring char8_t(20),char16_t(11起),char32_t(11):指定占用字节数且是无符号,字符串类u8string,u16s…

传闻Google谷歌代投印度slots游戏广告效果备受关注

传闻Google谷歌代投印度slots游戏广告效果备受关注 在印度&#xff0c;随着互联网的普及和移动设备的广泛使用&#xff0c;网络游戏和在线娱乐产业逐渐兴起。其中&#xff0c;“slots游戏”作为一种受欢迎的在线博彩形式&#xff0c;吸引了大量玩家。对于广告主而言&#xff0…