文件操作可以从两层接口理解C 标准库提供FILE *流Linux/POSIX 接口使用整数形式的文件描述符。两层接口最终都与进程访问文件有关但它们提供的抽象和数据处理方式不同。本文从fopen、fprintf、fclose出发再衔接open、read、write、close最后整理文件描述符表。代码保留示例原有的变量名和操作顺序从注释中恢复的阶段片段会明确标出边界问题另外说明。一、文件包含内容也包含属性文件大小为 0并不代表文件不存在或不需要任何存储空间。除了内容文件还有权限、所有者、大小等元数据。访问文件内容和查看文件属性是不同的操作。对文件执行操作的主体是进程。进程通过文件接口请求操作系统完成访问内核维护打开文件所需的状态。进程中的程序C 标准 I/O 库底层文件接口内核管理的打开文件对象底层文件或设备打开文件是建立访问关系、取得访问入口不能直接理解成把整个文件内容一次性读入内存。后续读写才涉及具体数据普通文件数据还可能经过内核页缓存。log.txt是相对路径通常相对于进程的当前工作目录解析。程序放在哪个目录与程序启动后的工作目录并不必然相同。这与简易 Shell 中chdir改变工作目录的概念相衔接。二、C 文件接口先打开再读写最后关闭下面是追加写入的完整示例保留原代码及其中用于切换观察的注释#includestdio.h#includestring.hintmain(){FILE*fpfopen(log.txt,a);if(fpNULL){perror(fopen);return1;}constchar*msghello bite!\n;fprintf(fp,%s,msg);fclose(fp);//printf(hello world\n);//fprintf(stdout, hello fprintf\n);//const char *msg hello fwrite\n;//fwrite(msg, strlen(msg), 1, stdout);return0;}可以按三步阅读fopen(log.txt, a)打开或创建文件获得流指针失败返回NULL。fprintf(fp, %s, msg)把格式化输出写到fp对应的流。fclose(fp)完成流的收尾并关闭关联文件描述符。fp指向库管理的流对象不是磁盘内容的起始地址。程序中的msg是要写出的文本fp是操作入口两者不要混淆。保存为myfile.c编译与观察方式为gcc myfile.c-omyfile ./myfilecatlog.txt按代码分析每次成功运行都会追加一行hello bite!。这里给的是观察方法不是当前环境中的实测记录。w 和 a 的区别模式文件不存在时文件已存在时r打开失败允许读取w创建截断为 0再写入a创建保留内容写入时追加到末尾因此“写文件”并不自动表示“追加”。将示例中的a改为w已有内容就会在打开时被清空。这是打开方式决定的与后面选用fprintf还是fwrite是两回事。三、标准流与输出接口程序通常具有三个标准流标准流含义常见终端场景stdin标准输入从终端读取输入stdout标准输出向终端输出结果stderr标准错误向终端输出诊断信息它们的类型都是FILE *。连接终端只是常见情况重定向后可以连接文件或其他对象。上面代码注释中的三种输出分别是printf(hello world\n);fprintf(stdout,hello fprintf\n);constchar*msghello fwrite\n;fwrite(msg,strlen(msg),1,stdout);这是恢复注释后的观察片段应分别放入合适的作用域测试避免与已有msg重复定义。printf默认使用stdoutfprintf显式指定流并按格式输出fwrite按指定大小和数量写出数据。fwrite(msg, strlen(msg), 1, stdout)表示写一个数据项每项长度为strlen(msg)字节。fwrite返回的是完整写出的项数不是固定返回字节数。同理fread的返回值也按项计数。fread 读文件片段中的一个细节另一个读取示例里有这样的原语句intnfread(buffer,sizeof(buffer)-1,1,fp);if(n0){printf(%s,buffer);}这里尝试读取一个较大的数据项。若文件末尾剩余内容不足一整项可能已有部分字节读入数组而返回的完整项数仍为 0只在n 0时打印就可能漏掉末尾数据。因此不能把这个片段当作已经完善的cat实现。它还需要区分 EOF 与读取错误。此处保留原语句用于解释参数含义不将改写后的读取程序混入示例主线。四、open用文件描述符操作文件从 C 标准库向下看打开文件可以使用intfdopen(log.txt,O_CREAT|O_WRONLY|O_TRUNC,0666);相关头文件包括sys/types.h、sys/stat.h、fcntl.hread、write、close声明在unistd.h中。open成功返回非负整数也就是文件描述符失败返回-1。原代码使用if(fd 0)检查失败不能改成fd 0因为0也是有效编号。flags访问模式与附加选项标志含义O_RDONLY只读O_WRONLY只写O_RDWR读写O_CREAT不存在时创建O_TRUNC在可写打开普通文件时截断内容O_APPEND每次写入时定位到文件末尾前三种访问模式选择一个再通过按位或|组合附加选项。位标志示例中的ONE_FLAG | TWO_FLAG用来组合选项flags ONE_FLAG用来检查某一位但文件访问模式不能全部当成独立开关特别是O_RDONLY的值为 0。两个关键对应关系是// 对应 w 的创建、截断写语义intfdopen(log.txt,O_CREAT|O_WRONLY|O_TRUNC,0666);// 对应 a 的创建、追加写语义intfdopen(log.txt,O_CREAT|O_WRONLY|O_APPEND,0666);两行是可替换的观察语句不是在同一作用域连续定义两次fd。O_CREAT只表示允许创建不自动截断已有内容清空与追加分别由O_TRUNC和O_APPEND决定。mode 与 umask使用O_CREAT时需要提供创建权限参数。0666是八进制数在未涉及默认 ACL 的通常情形下新文件权限由mode ~umask得到。例如0666与0022的掩码组合后为0644。示例中的umask(0)用于观察不屏蔽权限位的结果并非每次创建文件都必须调用。打开已有文件时0666也不会重新设置原文件权限。五、read 与 write接口传递的是字节原示例先把整数转换为文本再写出inta1234567;charbuffer[16];snprintf(buffer,sizeof(buffer),%d,a);write(fd,buffer,strlen(buffer));这段摘录省略了外围循环保留原来的变量和转换方式。写出的内容是字符1234567不是整数对象在内存中的原始表示。文本表示如何生成是程序的选择write接收地址和长度按字节传输。长度采用strlen(buffer)不包含 C 字符串末尾的\0。文件不要求以空字符作为结束标志。下面是从注释中恢复的原read循环片段前提是fd已经成功以可读方式打开while(1){charbuffer[64];intnread(fd,buffer,sizeof(buffer)-1);if(n0){buffer[n]0;printf(%s,buffer);}elseif(n0){break;}}理解时区分三种返回值n 0实际读到了n个字节。代码预留一字节并设置buffer[n] 0后按字符串输出。n 0到达文件末尾退出循环。n 0发生错误原循环没有处理这个分支可能反复重试。write成功返回实际写入的字节数也可能少于请求长度。原示例没有完整处理短写和中断这些边界应与接口基本流程分开理解。六、为什么打开文件常得到 3、4、5、6下面恢复的是连续打开四个文件的原片段需要放在包含相应头文件的main中观察umask(0);intfd1open(log1.txt,O_CREAT|O_WRONLY|O_TRUNC,0666);intfd2open(log2.txt,O_CREAT|O_WRONLY|O_TRUNC,0666);intfd3open(log3.txt,O_CREAT|O_WRONLY|O_TRUNC,0666);intfd4open(log4.txt,O_CREAT|O_WRONLY|O_TRUNC,0666);if(fd10)exit(1);if(fd20)exit(1);if(fd30)exit(1);if(fd40)exit(1);printf(fd1: %d\n,fd1);printf(fd2: %d\n,fd2);printf(fd3: %d\n,fd3);printf(fd4: %d\n,fd4);close(fd1);close(fd2);close(fd3);close(fd4);在常见启动环境中进程的0、1、2已经分别用于标准输入、标准输出和标准错误。因此后续打开文件时经常依次得到3、4、5、6。描述符常见含义对应的 C 标准流0标准输入stdin1标准输出stdout2标准错误stderr分配原则是当前进程中最小的未使用编号。返回3是常见现象而非固定规则。关闭某个编号后后续打开可以复用它不同进程里的相同 fd也不一定指向同一个文件。原代码还通过stdin-_fileno等成员观察关联编号。这属于特定库的实现细节不是通用 C 接口。作为补充POSIX 环境中可用fileno(stdin)等公开接口取得关联描述符。七、文件描述符是表的索引从内核角度可以先建立这样的简化模型进程 task_structfiles_struct管理文件描述符表表项 0、1、2、3……内核 struct file 对象文件位置、打开标志及底层对象用户态 FILE 流对象关联的整数 fd这是概念关系图省略了具体内核结构层级。进程用 fd 索引表项表项关联内核打开文件对象。整数 fd 不是struct file也不是文件内容地址。一个进程可以打开多个文件同一个文件也可以被多次打开。文件名、文件描述符、打开文件对象属于不同层次不能相互等同。C 标准库在用户态维护流状态和缓冲等信息最终借助底层接口完成数据传输。因此一次fprintf调用不一定立刻对应一次write系统调用。标准 C I/O 的跨平台接口也由各平台的库实现去衔接不同底层系统。八、衔接重定向为什么仍能使用 fgets后续代码将输入文件接到标准输入关键原语句是intfdopen(argv[1],O_RDONLY);if(fd0)exit(1);dup2(fd,0);close(fd);while(1){charbuffer[64];if(!fgets(buffer,sizeof(buffer),stdin))break;printf(%s,buffer);}这是已有命令行参数检查之后的原代码片段。它把fd所指向的打开文件关联到描述符0因此之后fgets(..., stdin)的输入来源变成该文件。改变的是描述符关联读取调用本身没有换成另一套接口。在通常open得到3等其他编号且dup2成功的情况下关闭原fd后编号0仍保留关联。如果打开时0本来就是空位fd可能正好等于0此时直接close(fd)就会关闭标准输入原示例没有处理这种情况也未检查dup2失败。重定向的完整行为留到下一篇展开。九、复习时把三层分开层次主要对象关注的问题C 标准库FILE *流、格式化输出与缓冲进程文件接口整数 fd用哪个编号读取、写入或关闭内核管理打开文件对象打开状态、读写位置与底层对象先沿着fopen → fprintf → fclose理解一次写入再沿着open → read/write → close理解按字节访问。看到0、1、2时想到标准输入输出的约定看到 fd 时想到进程的描述符表索引。本文保留的是各阶段示例多个片段不能直接无差别拼接成一个main。返回值检查、读写错误、短写和持久化等问题没有通过另写一个完整程序替换原有学习顺序。
企业数字化 ERP 产品动态
相关推荐
XSS 攻击与防御 10.1 XSS 攻击与防御XSS 的本质可以类比为在网页里混入一段不受信任的剧本,浏览器无法区分脚本是业务本身的代码还是攻击者注入的内容,会直接解析执行,窃取数据、劫持页面、诱导跳转。10.1.1 XSS 分类:反射型、存储型、DOM 型XSS&… · 2026/11/4 2:35:15
AgentEvals(agentevals-cli)Agent评测方法与步骤 AgentEvals(agentevals-cli)Agent评测方法与步骤
框架定位与核心原理
业内常说的 AgentEvals 官方全称为 agentevals-cli,是 Strands Labs 开源的框架无关、OpenTelemetry(OTel) Trace 驱动的Agent评测工具,核心设计理念是「一次… · 2026/11/4 2:35:15
渗透测试工程师成长指南:从基础到实战 1. 渗透测试行业的真实挑战作为一名从业多年的网络安全工程师,我见过太多怀揣黑客梦想的年轻人,在接触渗透测试后迅速被现实击垮。这个行业远没有影视作品中那么光鲜亮丽,背后是无数个熬夜研究漏洞的夜晚和持续不断的学习压力。1.1 技术门槛&… · 2026/11/4 3:25:24
PostgreSQL慢SQL排查与优化实战指南 1. 慢SQL问题排查的必要性数据库性能问题就像汽车发动机的积碳——平时感觉不到,一旦爆发就会让整个系统瘫痪。作为PostgreSQL DBA,我处理过上百个慢SQL案例,其中80%的生产事故都是由于未被及时发现的问题SQL逐渐累积导致的。上周刚处理过一个… · 2026/11/4 3:25:24
多目标跟踪实战:检测、预测与匹配的工程取舍 简介:这份资源面向计算机视觉与信号处理方向的学习者,聚焦多目标跟踪(MTT)在MATLAB环境下的实现,适合希望从目标检测、状态估计到数据关联完整走通一遍流程的初中级读者。压缩包共3个文件,以m脚本、avi视频… · 2026/11/4 3:25:24
PostgreSQL慢SQL问题排查与优化实战指南 1. 慢SQL问题排查的必要性上周五凌晨两点,我被一阵急促的电话铃声惊醒。运维同事告诉我生产环境的订单查询接口响应时间从200ms飙升到15秒,用户投诉已经塞满了客服系统。当我连上服务器查看pg_stat_activity视图时,发现有个查询已经运行了8分… · 2026/11/4 3:25:24
Unity等距解谜工程拆解:旋转、路径重算与二次开发实战 简介:这份资源是面向Unity初学者与进阶开发者的《纪念碑谷》风格解谜游戏完整工程,基于Unity 2017.3版本构建,可用于学习2D与3D图形结合、场景搭建、资源管理与C#脚本逻辑等核心开发技能。压缩包共254个文件,约2.61MB,… · 2026/11/4 3:25:24
全屏歌词动画实现指南:Folia内置模式解析与性能调优 全屏歌词动画这件事,很多人第一反应是"不就是把歌词放大铺满屏幕吗"。真上手做过一轮就知道,同样是全屏,有的方案歌词一放大就糊成一片,有的动效一跑起来帧率直接腰斩,还有的在不同分辨率屏幕上位置全乱。我… · 2026/11/4 3:24:24
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46
AI辅助技术栈评估:提升研发决策效率60% 1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年… · 2026/11/4 0:00:17
从生成Token到直接决策:Jev如何重塑AI Agent工程实践 1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你… · 2026/11/4 0:00:17
32G统一内存跑大模型:内存账、TPS实测与端云分流 想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统… · 2026/11/4 0:00:17
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46