Linux学习之路 -- 文件 -- 文件操作

news2024/11/24 5:00:26

在学习C语言时,我们就学习过文件相关的内容,但是由于知识储备尚且不足,无法深入的了解文件,下面我们就要重新认识一下文件。

<1> 简单介绍(铺垫)

1.前面我们说过,文件 = 内容 + 属性,所以我们对文件的操作也就分为对属性和内容的操作。

2.通常我们在访问文件之前,都得先打开文件,打开文件这个操作就必须通过执行代码的方式来完成修改。 而修改这个动作是由cpu来执行的,cpu只能通过访问内存的方式来执行代码修改文件, 所以文件必需被加载到内存中,方便cpu对其进行修改。

3. 是谁打开的文件呢?我们执行修改文件代码前,这段代码会先变成进程,然后再由cpu调度进程打开文件。所以实际上打开文件的是进程。

4.一个进程可以打开多少文件?进程是可以打开多个文件

总结一下上面四点,在一定的时间段内,系统中存在多个进程,同时可能存在更多的被打开的文件,操作系统肯定是要管理这些文件,根据先描述,再组织的原则,内核中一定会有描述被打开文件的数据结构(这里假定是struct),并且用其定义对象。后面要研究的问题就变成了PCB和struct XXX的关系。当然,上述的文件都是被打开的文件,也叫内存文件。至于没有打开文件,一般就在磁盘上。

<2>重温一下C语言的文件接口 -对比一下重定向

下面主要重新介绍一下文件的打开,关闭和读写函数。由于文件操作函数在C语言阶段已经有所涉猎,所以这里重点介绍与重定向的关系。

在介绍它们的关系之前,我们先回顾一下文件函数的相关参数。

pathname表示路径名称,但实际上我们只要输入文件名即可,默认是在当前路径下查找(原因后面介绍)。mode主要是打开文件的模式,这里主要介绍一下w,r,a。其他的模式大同小异,大家可自行查阅复习。

其中W就是表示以写方式打开文件,如果文件不存在,就自动创建该文件。

#include<stdio.h>
#include<unistd.h>
#include<string.h>

#define filename "file.txt"
int main()
{
    FILE* p = fopen(filename,"w");
    if(p == NULL)
    {
        perror("fopen");
    }

    fclose(p);
}

运行结果:

下面我们再用文件读写函数对文件进行写入,这里为了方便显示,我们使用fputs函数

这个函数的参数就是把s这个字符串打印到stream这个文件流里面,这个文件流就是其实就可以看成是文件。

演示代码

#include<stdio.h>
#include<unistd.h>
#include<string.h>

#define filename "file.txt"
int main()
{
    FILE* p = fopen(filename,"w");
    if(p == NULL)
    {
        perror("fopen");
    }
    const char* str = "hello world\n";
    fputs(str,p);
    fclose(p);
}

上面这段代码其实很简单,我们把写入文件的操作去掉,再次运行代码,就会发现文件内容被清空,这是因为文件以W方式打开,会以覆盖的方式写入(就是在打开文件时会清空文件)。下面我们如果我们用echo命令重定向一下,我们再看一下文件的内容。

我们可以发现,重定向的操作其实和文件以读方式打开文件效果上是一样的,所以我们可以推出输出重定向时就是文件以(w)读的方式打开。

同理可得,我们可以推出,当我们使用追加重定向和输出重定向时,就是以a(append) 和 r(read)的方式打开文件。

文件操作在默认在当前路径的原因

我们在执行文件操作时,一定是由进程来实施操作。而我们之前说过/proc目录下,存在关于进程的大量信息,其中里面包含了进程当前的所处路径cwd。

下面复用上文的代码演示一下

#include<stdio.h>
#include<unistd.h>
#include<string.h>

#define filename "file.txt"
int main()
{
    FILE* p = fopen(filename,"w");
    if(p == NULL)
    {
        perror("fopen");
    }
    const char* str = "hello world\n";
    printf("pid: %d\n",getpid());
    while(1)
    {
        fputs(str,p);
        sleep(2);
    }
    fclose(p);
    return 0;
}

进程的信息和相关结果

如果我们需要修改文件路径,我们就可以使用chdir函数,修改进程的工作路径,此时我们再运行程序,文件就会在修改后的路径里面被创建。

程序默认打开的文件流

一般来说,我们写的程序都是向显示器这个文件打印,但是我们自己却从来没有打开过显示器文件,而我们默认就能使用该文件进行打印,说明系统在打印之前就帮我们打开了文件。其中这里的文件包含了好几个

stdin输入流文件,叫做标准输入,默认是键盘设备;stdout输出流文件,叫做标准输出,默认是显示器设备;stderr 叫做标准错误,默认是显示设备。stdout可以从stdin里面读取信息,然后将其打印到显示屏上。而这些文件流是可以直接使用。

下面用一些接口来演示一下stdout这个输出流

#include<stdio.h>
#include<unistd.h>
#include<string.h>

#define filename "file.txt"
int main()
{
    printf("hello world\n");
    fprintf(stdout,"hello world\n");
    fputs("hello\n",stdout);
}

运行结果

stdin输入流和stdout输出流类似,只不过一个是做输入一个做输出,我们读取数据时可以从stdin里面进行读取,而读取操作就可以使用scanf,fscanf等函数,下面就不具体演示了。而stderr先简单了解即可,后面再叙述。

<3>文件操作的系统调用接口

我们所使用的文件大多在磁盘进行存储,而磁盘属于底层的硬件,我们作为用户是无法直接修改底层硬件的数据,只有操作系统才有权力修改。虽然我们能够使用一些C语言的文件操作接口对文件进行修改,但这些接口最后都是封装的系统调用,下面我们就来聊一聊文件操作相关的系统调用。

<1>open

该接口用于打开文件,返回值为一个整数,如果打开成功,就会返回一个整数,这个整数叫做文件描述符,而文件如果打开失败,就返回-1。

这里的pathname字符串记录着要打开文件的名称,flags这个整数表示打开文件的方式, 我们一般用宏来表示这些方式。这些宏一般是用位图的方式来区分的,简单点说就是在32个比特位上的0变为1,不同的宏变化的比特位是错位的。这样我们就能使用按位或的操作实现用一个整数表示多个文件打开方式(按位或:两个比特位均为零才是零,其余皆是1)。

下面的宏代表了文件打开的各种模式

  1. O_RDONLY: 以只读方式打开文件。
  2. O_WRONLY: 以只写方式打开文件。
  3. O_RDWR: 以读写方式打开文件。
  4. O_APPEND: 追加数据到文件末尾。
  5. O_CREAT: 如果文件不存在,则创建它。
  6. O_EXCL: 与 O_CREAT 一起使用,如果文件已存在,则返回错误。
  7. O_TRUNC: 如果文件已存在,则截断它到零长度。(清空文件内容 )
  8. O_NONBLOCK: 非阻塞模式打开文件。
  9. O_SYNC: 同步写入,数据立即写入磁盘。
  10. O_DSYNC: 同步写入,数据写入磁盘后再返回。
  11. O_RSYNC: 同步读取,读取操作等待数据写入磁盘完成后进行。
  12. O_NOCTTY: 防止文件成为控制终端。
  13. O_CLOEXEC: 在执行 exec 函数族后自动关闭文件描述符。

如果我们要实现fopen中的w功能,我们就可以给flag参数传 O_RDONLY | O_CREAT。

如果我们使用第二个open系统调用接口,mode就表示文件的权限,这个带mode参数的系统open接口是在文件不存在时调用,mode参数就表示在创建文件时的文件权限。如果是正常的普通文件,我们输入0666即可。需要注意的是,文件的权限还受权限掩码的约束,所以我们输入的文件权限并不是最终的文件权限。当然,如果不想受权限掩码的约束,我们直接调用umask的系统调用接口,并且直接将权限掩码设置为零即可

<2>close

当我们对文件的操作结束时,我们就需要关闭文件,此时我们就可以使用close接口来关闭文件。这个接口的使用非常简单只需要将open接口的返回值传入close即可。

<3>write

write接口就是向文件里面写入内容,其操作和fwrite差不多。

fd就是文件描述符,buf就是要写入文件的内容的头指针,count表示写入文件字节总数。

下面演示一下,用w方式打开文件,并写入一些内容

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/types.h>

#define filename "file.txt"
int main()
{
    int fd = open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);
    if(fd == -1)
    {
        perror("open fail");
        return 1;
    }

    const char* str = "hello world\n";
    write(fd,str,strlen(str));
    close(fd);
    return 0;
}

结果

如果我们要追加,就可以把O_TRUNC修改成O_APPEND即可,通过灵活运用各种宏的组合,我们就可以实现C语言中文件操作的各种特性。

以上就是所有内容,文中如有不当之处,还望各位大佬指正,谢谢!!!

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

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

相关文章

ThreeJS:坐标辅助器与轨道控制器

ThreeJS与右手坐标系 使用ThreeJS创建3D场景时&#xff0c;需要使用一个坐标系来定位和控制对象的位置和方向。 ThreeJS使用的坐标系是右手坐标系&#xff0c;即&#xff1a;X轴向右、Y轴向上、Z轴向前&#xff0c;如下图所示&#xff0c; ThreeJS-右手坐标系 Tips&#xff1a;…

java技术栈快速复习05_基础运维(linux,git)

Linux知识总览 linux可以简单的理解成和window一样的操作系统。 Linux和Windows区别 Linux是严格区分大小写的&#xff1b;Linux中一切皆是文件&#xff1b;Linux中文件是没有后缀的&#xff0c;但是他有一些约定俗成的后缀&#xff1b;Windows下的软件一般是无法直接运行的Li…

JDK14特性

JDK14 1 概述2 语法层面的变化1_instanceof的模式匹配(预览)2_switch表达式(标准)3_文本块改进(第二次预览)4_Records 记录类型(预览 JEP359) 3 API层面的变化4 关于GC1_G1的NUMA内存分配优化2_弃用SerialCMS,ParNewSerial Old3_删除CMS4_ZGC on macOS and Windows 4 其他变化1…

《Git---Windows Powershell提交信息中文乱码解决方案》

解释&#xff1a; Windows PowerShell中的Git乱码通常是因为字符编码不正确或Git配置不支持Windows系统的默认编码导致的。Git在处理文件时可能使用UTF-8编码&#xff0c;而Windows系统的命令行工具&#xff08;如PowerShell&#xff09;默认使用的是Windows-1252或GBK编码。 …

Unity Animation--动画剪辑

Unity Animation--动画剪辑 动画剪辑 动画剪辑是Unity动画系统的核心元素之一。Unity支持从外部来源导入动画&#xff0c;并提供创建动画剪辑的能力使用“动画”窗口在编辑器中从头开始。 外部来源的动画 从外部来源导入的动画剪辑可能包括&#xff1a; 人形动画 运动捕捉…

3.4 无关、基和维度

这一节是关于子空间的真实大小。对于 m n m\times n mn 的矩阵&#xff0c;它有 n n n 个列&#xff0c;但是它真正的维数不一定为 n n n&#xff0c;维数可以由无关列的个数来得到。列空间的实际维度就是秩 r r r。 无关的概念是用于向量空间中的任意向量 v 1 , . . . ,…

C++入门第二节--关键字、命名空间、输入输出

点赞关注不迷路&#xff01;本节涉及c入门关键字、命名空间、输入输出... 1. C关键字 C总计63个关键字&#xff0c;C语言32个关键字 asmdoifreturntrycontinueautodoubleinlineshorttypedefforbooldynamic_castintsignedtypeidpublicbreakelselongsizeoftypenamethrowcaseen…

【Java EE】CAS原理和实现以及JUC中常见的类的使用

˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如…

OpenCV如何在图像中寻找轮廓(60)

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV如何模板匹配(59) 下一篇 :OpenCV检测凸包(61) 目标 在本教程中&#xff0c;您将学习如何&#xff1a; 使用 OpenCV 函数 cv::findContours使用 OpenCV 函数 cv::d rawContours …

ROS机器人入门:机器人系统仿真【学习记录】——1

最近闲来无事&#xff0c;重温了一下ROS方面的相关知识。先前的学习都是一带而过&#xff0c;发现差不多都忘了&#xff0c;学习的不够深入。因此&#xff0c;在重温的同时&#xff0c;于先前写下了2篇ROS架构与通信机制的博客&#xff1a; 对应的博客的链接为&#xff1a; R…

【副本向】高等级副本全流程开发

副本的创建 1.从配置表通过副本ID获取此副本参数 Tab_CopyScene rCopyScene TableManager.GetCopySceneByID(m_CopySceneID);if (rCopyScene ! null){//只要配置了组队的Rule&#xff0c;就是组队模式&#xff0c;否则就是单人模式bool bSolo true;for (int n 0; n < rCo…

菜鸡学习netty源码(三)—— Reactor 模型

1.概述 我们先进行理解一下Reactor模型&#xff0c;知道什么是Reactor模型&#xff0c;它有什么特别之处。我们先来简单介绍一下这个Reactor模型。 Reactor模型的核心思想&#xff1a; 就是将所关注的I/O事件进行注册到一个多路复用器上&#xff0c;一旦有I/O事件的发生&#…

Debian 12 -bash: netstat: command not found 解决办法

问题表现&#xff1a; debian 12系统中&#xff0c;不能使用 netstat命令 处理办法&#xff1a; netstat 命令就的net-tools中&#xff0c;把net-tools工具安装上就好了。 apt-get install netstat 安装之后就可以使用netstat 命令了&#xff0c;如查询端口情况&#xff1a; …

快速排序的单趟排序方法对比

这里的霍尔法内容来自文章&#xff1a;【排序算法】快速排序&#xff08;C语言&#xff09;_c语言快速排序-CSDN博客 霍尔法 单趟排序使用霍尔法&#xff0c;这样的话我们必须保证除了指针停留的位置到头之外&#xff0c;最后首尾指针共同指向的是一个比key小的值&#xff0c…

启动盘制作

魔术师pe安装教程 我一般使用魔术师来安装windows系统 魔术师pe地址下载 解压后使用 把ios映像文件放入pe系统u盘下 开机按f1,进入bios,将usb接口拉到本电脑&#xff0c;在按f10保存&#xff0c;在按f12即可找到pe的u盘 ventoy安装教程 其他系统安装我使用ventoy ventoy地…

一个5000刀的XSS

背景介绍 今天分享国外一个白帽小哥Crypto通过发现Apple某网站XSS而获得5000美元赏金的故事。废话不多说&#xff0c;让我们开始吧&#xff5e; 狩猎过程 易受攻击的 Apple 服务网站是&#xff1a;https://discussions.apple.com&#xff0c;该服务是苹果用户和开发者讨论问题…

【笔记】Simulink与Workbench交互+自定义m函数封装为Simulink模块

以如下三角函数为例&#xff0c;说明建模方法 ya*sin(b*2*pi*uc);0.总模型总代码 总模型 总代码&#xff1a; clc clear close allt_all10; a10; b1; c0;%pi/2; delta_t0.01; simOutsim(test240430); out_tsimOut.tout; out_y1simOut.yout{1}.Values; out_y2simOut.yout{2}.…

栈的磁盘优化:降低存取成本的算法与实现

栈的磁盘优化&#xff1a;降低存取成本的算法与实现 问题背景简单实现方法的分析实现方法PUSH操作POP操作成本分析渐近分析 优化实现方法实现方法成本分析渐近分析 进一步优化&#xff1a;双页管理策略实现方法管理策略成本分析 伪代码示例C代码示例结论 问题背景 在具有有限快…

WAAP动态安全解决方案

随着企业数字化进程不断加速&#xff0c;应用安全面临多重威胁&#xff0c;新型攻击方式层出不穷&#xff0c;常见的攻击形式包括Web应用攻击、DDoS攻击、API攻击、恶意爬虫攻击等。企业正面临严峻的安全防护挑战&#xff0c;需寻找一个可靠、全面的安全解决方案。在此情况下&a…

题目:吃奶酪

问题描述&#xff1a; 解题思路&#xff1a; 枚举每种吃奶酪顺序&#xff0c;并计算其距离&#xff0c;选择最小的距离即答案。v数组&#xff1a;记录顺序。 注意点&#xff1a;1. 每次用于min的s需要重置为0。 2. 实数包括小数&#xff0c;所以结构体内x,y为double类型。 3. 第…