【Linux】基础IO(一):C 接口文件讲解


✨道路是曲折的,前途是光明的!

📝 专注C/C++、Linux编程与人工智能领域,分享学习笔记!

🌟 感谢各位小伙伴的长期陪伴与支持,欢迎文末添加好友一起交流!

  • 一、文件核心认知
    • [1.1 文件的基础属性与分类](#1.1 文件的基础属性与分类)
    • [1.2 进程与打开文件的关系](#1.2 进程与打开文件的关系)
    • [1.3 补充(关联系统层面认知)](#1.3 补充(关联系统层面认知))
  • 二、C语言文件IO
    • [2.1 打开文件](#2.1 打开文件)
    • [2.2 思考:打开文件所在的位置?](#2.2 思考:打开文件所在的位置?)
    • [2.3 写入文件](#2.3 写入文件)
    • [2.4 默认打开的三个流](#2.4 默认打开的三个流)

一、文件核心认知

1.1 文件的基础属性与分类

  1. 文件本质:文件 = 内容 + 属性,即使是0KB空文件也占用磁盘空间(存储属性)。
  2. 文件分类与核心问题
  3. 未打开的文件:存储在磁盘上,核心问题是"存储与管理"------通过分门别类的组织方式实现文件的快速增删查改;
  4. 打开的文件:由进程打开,核心是研究"进程与文件的关系",也是本文的核心研究目标。

1.2 进程与打开文件的关系

  1. 加载逻辑
  • 文件被打开时会加载到内存;进程启动时,操作系统默认打开 stdin、stdout、stderr 三个文件流,一个进程可打开多个文件,因此进程与打开的文件是 1:n(一对多) 的关系。
  1. 系统管理逻辑
  2. 操作系统需管理大量被打开的文件,遵循 "先描述、再组织" 的核心原则;
  3. 描述: 内核为每个打开的文件创建"文件打开对象"(结构体),包含文件属性等关键信息;
  4. 组织: 文件打开对象通过内置指针链接成双链表,将对文件的管理转化为对双链表的增删查改操作。

1.3 补充(关联系统层面认知)

  • 狭义上文件是磁盘(永久存储外设)上的存储单元,对文件的操作本质是对磁盘的IO;广义上Linux"一切皆文件",硬件均被抽象为文件管理;
  • 文件读写并非直接通过C/C++语言实现,而是依赖操作系统提供的文件系统调用接口。

二、C语言文件IO

从"文件小白"到"IO大侠":C语言文件操作全攻略-CSDN博客

2.1 打开文件

向一个文件写入内容,我们肯定得先打开文件,但是为了避免文件打开占用内存资源,造成资源泄漏,所以打开后我们需要关闭文件。这里我们需要使用到两个函数fopen,fclose


  1. fopen

fopen 打开文件,失败返回 NULL,成功返回指向 FILE 结构体的指针(通过该指针操作文件);我们在这里仅研究 w(写)、a(追加写)两种打开方式。

  1. fclose
  • 这里我们以写的方式打开和关闭文件!
c 复制代码
#include <stdio.h>

int main()
{
  FILE* fp = fopen("hello.txt", "w");
  if(fp == NULL)
  {
    perror("fopen");
    return 1;
  }

  fclose(fp);

  return 0;
}

我们先查看一下当前目录,发现是没有hello.c这个文件的,然后当我们运行后再查看会发现hello.c的文件出现了。

所以当我们以w的方式打开一个不存在的文件的时候,他会给我们自动创建一个以这个名字命名的文件


2.2 思考:打开文件所在的位置?

我们先更改一下代码

这样我们能知道进程的pid码,然后就可以使用ls /proc/[进程id] -l命令查看当前正在运行进程的信息

进程可通过两个关键符号链接确定路径:

  • cwd:指向进程当前运行目录;
  • exe:指向启动进程的可执行文件完整路径。

因此进程打开/创建文件时,即便文件不带路径,操作系统也能通过进程的cwd确定文件的存放位置(本质是进程打开文件,进程自身知晓路径上下文)。

注意:有绝对路径时 :操作系统直接按指定的绝对路径创建文件,不再拼接cwd路径。


2.3 写入文件

当我们像写入内如到打开的文件时,我们可以使用fwrite()函数

fwrite 可向以w/a方式打开的文件写入内容,传入参数包括字符串、单份字符串大小、份数、文件流;

写入字符串时,无需将strlen计算的长度+1(即不写入 \0 ------因为\0是C语言区分字符串的专属规则,文件存储的是通用字节流,需适配多语言读取,仅需写入字符串实际内容即可。

c 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

int main()
{
  FILE* fp = fopen("hello.txt", "w");
  if(fp == NULL)
  {
    perror("fopen");
    return 1;
  }

  const char* message = "wbushidaitou\n";
  //const char* message = "Hello! Daitou\n";
  fwrite(message, strlen(message), 1, fp);

  fclose(fp);

  return 0;
}

当我们重新写入不同的内如发现之前写进去的内容被清空了,这是为什么?

<font style="color:rgb(85, 86, 102);background-color:rgb(238, 240, 244);">w</font>方式fopen打开文件时,写入前会先清空文件原有内容,后续通过fwrite写入的内容会从头覆盖,因此最终文件中仅保留新写入的内容(如仅显示"Hello! Daitou")。

  • 我们讲写入的方式从w改成a来试试
c 复制代码
 FILE* fp = fopen("hello.txt", "a");

a方式fopen打开文件写入:保留原有内容,仅在文件末尾追加写入新内容(不会清空/覆盖原有内容)。


2.4 默认打开的三个流

linux下一切皆文件,c语言程序在启动的时候,默认会为我们打开三个输入输出流(文件):

  • stdin是键盘文件(c++中是cin)
  • stdout是显示文件(c++中是cout)
  • stderr是显示器文件(c++中是cerr)
  1. 其中,标准输入流对应的设备就是键盘,标准输出流和标准错误流对应的设备都是显示器。
  2. 查看man手册我们就可以发现,stdin、stdout以及stderr这三个家伙实际上都是FILE*类型的。
c 复制代码
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;

所以我们就可以使用fprintf向显示器文件stdout以及stderr中输入,看显示器是否会进行显示

fprintf 用法与 printf 类似,核心差异在于输出目标:

  • printf:默认将内容输出到显示屏(stdout)
  • fprintf:需显式指定输出的文件流(如指向 log.txt 的 FILE* 指针),可将内容写入任意指定文件。
c 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

int main()
{
  FILE* fp = fopen("log.txt", "w");
  if(fp == NULL)
  {
    perror("fopen");
    return 1;
  }

  const char* message = "Daitou\n";
  
  fprintf(stdout, "%s", message);
  fprintf(stderr, "%s", message);

  fclose(fp);

  return 0;
}

因此可直接使用 stdout/stderr(如 fprintf (stdout/stderr, ...))输出内容到显示器,无需手动打开即可操作,这也验证了进程启动时默认关联核心输入输出文件的特性。


✍️ 坚持用 清晰易懂的图解 + 可落地的代码,让每个知识点都 简单直观!

💡 座右铭 :"道路是曲折的,前途是光明的!"

相关推荐
杰克崔2 小时前
内核里的__private变量的使用及sparse
linux·运维·服务器·车载系统
啊阿狸不会拉杆2 小时前
《机器学习》 第 9 章 - 深度强化学习
人工智能·算法·机器学习·计算机视觉·ai·ml
沛沛老爹2 小时前
从Web到AI:多模态Agent Skills开发实战——JavaScript+Python全栈赋能视觉/语音能力
java·开发语言·javascript·人工智能·python·安全架构
0x532 小时前
JAVA|智能仿真并发项目-进程与线程
java·开发语言·jvm
黎雁·泠崖2 小时前
Java静态方法:用法+工具类设计+ArrayUtil实战
java·开发语言
陈希瑞2 小时前
GitHub Skill Forge 深度解析:把任意 GitHub 仓库一键锻造成 AI 可调用“技能包”
人工智能·github
工藤学编程2 小时前
零基础学AI大模型之LLM存储优化:大量QA与长对话问题实战
人工智能
徐礼昭|商派软件市场负责人2 小时前
AI 重构网购体验:从 “将就” 到 “讲究” 的消费者进化史|徐礼昭
大数据·人工智能·重构·智能客服·零售·智能搜索·ai推荐
ViiTor_AI2 小时前
视频水印怎么去?8 款免费视频水印去除工具实测对比(不模糊)
人工智能·音视频