网站网络架构中信云做网站
2026/4/6 5:57:23 网站建设 项目流程
网站网络架构,中信云做网站,google关键词排名,如何在网站后台备份数据库9.1 文件概述 引言#xff1a;让程序拥有记忆的能力 你好#xff0c;我是C语言之父丹尼斯里奇。今天#xff0c;我要和你分享C语言中最实用、最强大的功能之一——文件操作。想象一下#xff0c;如果人类没有记忆#xff0c;每次醒来都忘记昨天发生的一切让程序拥有记忆的能力你好我是C语言之父丹尼斯·里奇。今天我要和你分享C语言中最实用、最强大的功能之一——文件操作。想象一下如果人类没有记忆每次醒来都忘记昨天发生的一切生活会多么困难同样没有文件操作能力的程序就像没有记忆的人——每次运行都从零开始无法积累无法成长。让我给你讲个故事。1970年代当我和肯·汤普逊在贝尔实验室开发UNIX系统时我们意识到程序需要一种方式来持久保存数据。用户不想每次运行程序都重新输入所有信息系统也需要记录日志、配置和用户数据。于是我们在C语言中设计了一套优雅的文件操作机制这套机制至今仍然是现代编程语言文件操作的基础。学习文件操作是你的编程技能从玩具程序迈向实用工具的关键一步。掌握了文件操作你就能编写出真正有用的程序学生管理系统、文本编辑器、数据分析工具甚至小型数据库系统。9.1.1 什么是文件——计算机的记忆仓库生动的比喻从人类记忆到计算机文件让我们先通过几个比喻来理解文件的概念比喻1笔记本与计算机文件· 人类记忆你大脑中记住的知识易忘容量有限· 笔记本你写在纸上的笔记持久可随时翻阅· 计算机内存程序运行时的数据断电即失速度快· 计算机文件保存在硬盘上的数据持久可随时读取比喻2仓库与文件系统· 文件 仓库里的一个货物箱· 文件名 货物箱上的标签· 文件内容 箱子里的货物· 文件夹/目录 仓库里的货架· 文件路径 货物的具体位置如A区3排5号技术定义文件的本质在计算机科学中文件是存储在外部存储介质如硬盘、U盘、光盘等上的、具有名称的相关数据集合。这些数据被组织成连续的字节序列操作系统通过文件系统来管理它们。从C语言的角度看文件就是一个字节流——一连串的字节每个字节8位按顺序排列。无论文件内容是文字、图片还是音乐在C语言看来都是要处理的字节序列。// 文件在C语言中的抽象表示字节流[01001000][01100101][01101100][01101100][01101111]...对应字符 H e l l o...文件的组成要素每个完整的文件都包含以下要素文件名文件的标识符如report.txt· 主文件名“report”· 扩展名“.txt”表示文件类型文件内容实际存储的数据· 可以是文本、二进制数据等文件属性描述文件的元数据· 大小占用的存储空间· 创建时间、修改时间· 访问权限谁可以读、写、执行· 文件类型普通文件、目录、设备文件等文件位置在存储设备上的物理位置· 由文件系统管理对程序员透明文件的历史小故事有趣的是“文件这个概念并不是计算机发明的。在早期的打孔卡时代每张卡片就是一个文件”。后来磁带被用作存储介质时文件的概念开始形成——磁带上的一个数据段就是一个文件。到了磁盘时代文件系统变得更加复杂和强大但基本概念一脉相承。9.1.2 为什么要使用文件——程序能力的延伸内存的局限性为什么需要文件让我们先理解计算机存储的层次结构CPU寄存器 → CPU缓存 → 内存(RAM) → 硬盘/SSD → 光盘/磁带 速度最快 │ 速度最慢 容量最小 │ 容量最大 价格最贵 │ 价格最便宜 关键分界线持久性 内存断电数据丢失易失性 硬盘断电数据保留非易失性内存的问题容量有限通常只有几GB到几十GB价格昂贵每GB价格远高于硬盘易失性断电后数据全部丢失进程隔离一个程序不能直接访问另一个程序的内存文件的优势持久存储数据永久保存不受断电影响容量巨大现代硬盘可达数TB成本低廉每GB存储成本远低于内存数据共享多个程序可以访问同一个文件数据迁移文件可以复制、移动、备份文件在现实编程中的应用场景场景1配置文件的保存与读取// 程序启动时读取配置文件// 用户设置保存在 config.ini 中// 下次启动时自动加载用户偏好设置场景2数据持久化// 游戏进度保存// 玩家角色等级、装备、任务进度保存在 save.dat 中// 下次游戏时从文件中加载进度场景3大数据处理// 处理100万条学生记录// 不可能全部放在内存中// 从 students.csv 中逐条读取处理场景4日志记录// 程序运行日志写入 log.txt// 用于调试和监控程序运行状态// 即使程序崩溃日志仍然保存场景5数据交换// 程序A生成数据文件 data.json// 程序B读取该文件进行处理// 实现不同程序间的数据共享不使用文件的困境一个真实案例让我分享一个早期计算机用户的真实故事。在1970年代有一位研究员编写了一个复杂的科学计算程序需要输入5000个数据点进行计算。每次运行程序他都要在终端前花费数小时输入数据。有一天在他输入到第4999个数据时实验室突然停电了——所有数据丢失一切要从头开始。第二天他学会了使用文件。他将数据预先写入一个文件程序从文件中读取。即使停电数据文件还在只需要重新运行程序即可。这个教训告诉我们永远不要把重要数据只放在内存中。9.1.3 文件的分类——文本与二进制的本质区别直观理解人类语言 vs 机器语言文本文件就像人类写的信件——用人类能理解的字符写成你可以直接阅读。二进制文件就像机器内部的通信——用机器最熟悉的0和1表示对人类不友好但机器处理高效。深入解析文本文件什么是文本文件文本文件是完全由可打印字符组成的文件每个字符对应特定的编码如ASCII、UTF-8。文本文件的特点人类可读用文本编辑器可以直接查看和编辑编码依赖字符按特定编码方案存储有行结构通常按行组织每行以换行符结束平台差异不同系统换行符不同Windows: \r\n, Unix/Linux: \n, 经典Mac: \r文本文件的存储原理// 文本 Hello123 在文件中的存储ASCII编码字符 H e l l o123ASCII72101108108111495051二进制0100100001100101011011000110110001101111001100010011001000110011文本文件处理数字的代价intnumber12345;// 内存中4个字节取决于系统// 作为文本存储12345 → 5个字符 → 5个字节// 转换过程二进制整数 → 十进制字符串 → ASCII码深入解析二进制文件什么是二进制文件二进制文件按数据在内存中的原始形式存储不做字符转换。二进制文件的特点人类不可读用文本编辑器打开显示乱码无结构限制纯粹的字节序列无行概念平台相关数据表示可能因系统而异如字节序高效紧凑存储效率高处理速度快二进制文件的存储原理// 整数 12345 在二进制文件中的存储内存中的二进制形式假设32位小端序 低位字节 高位字节[00111001][00110000][00000000][00000000](57)(48)(0)(0)// 直接将这些字节写入文件不做转换详细对比文本文件 vs 二进制文件对比维度 文本文件 二进制文件本质 字符序列 字节序列可读性 人类可直接阅读 人类无法直接理解编辑工具 记事本、VS Code等文本编辑器 需十六进制编辑器或专用工具存储数字123 存储为3个字符’1’,‘2’,‘3’3字节 存储为整数的二进制形式通常2或4字节存储浮点数3.14 存储为字符’3’,‘.’,‘1’,‘4’4字节 存储为IEEE 754格式通常4或8字节换行处理 自动转换\n ↔ \r\n 无特殊处理字节原样读写平台移植性 较好但要注意换行符和编码 较差注意字节序、数据类型大小打开方式 “r”, “w”, a等 “rb”, “wb”, ab等适用场景 配置文件、源代码、日志、文档 图像、音频、视频、数据库文件、程序数据真实案例为什么图像用二进制而不用文本存储想象一下如果一张100万像素的彩色图片用文本存储· 每个像素有RGB三个值0-255· 如果用文本每个值需要1-3个字符加上分隔符· 大约需要 1,000,000 × 3 × 3 ≈ 9MB 存储空间而用二进制存储· 每个像素的RGB各占1个字节· 总共需要 1,000,000 × 3 3MB 存储空间节省了66%的空间 这就是二进制文件在存储媒体文件时的巨大优势。编码问题文本文件的隐藏挑战当C语言在1970年代诞生时ASCII编码0-127是主流。但今天我们需要处理全球各种语言// 不同编码下的你好存储ASCII不支持中文无法存储 GB2312简体中文C4 E3 BA C34字节 UTF-8UnicodeE4 BD A0 E5 A5 BD6字节 UTF-16Unicode604F7D594字节加上字节序标记重要建议现代C程序处理文本文件时应考虑使用UTF-8编码它是ASCII的超集兼容性好。9.1.4 C语言文件操作的核心概念文件指针C语言操作文件的遥控器在C语言中我们通过文件指针来操作文件。这是一个指向FILE结构体的指针包含了操作文件所需的所有信息。// FILE结构体的简化理解structFILE{intfd;// 文件描述符操作系统级别char*buffer;// 文件缓冲区指针size_tpos;// 当前读写位置size_tsize;// 文件大小intmode;// 打开模式读、写、追加等interror;// 错误标志inteof;// 文件结束标志// ... 其他内部信息};// 文件指针的定义和使用FILE*fp;// 声明文件指针fpfopen(data.txt,r);// 打开文件获取文件指针文件指针的作用标识文件哪个文件正在被操作跟踪位置当前读写到了文件的哪个位置管理缓冲区缓存数据以提高效率记录状态文件是否可读、是否出错、是否结束文件操作的标准流程四步曲C语言文件操作遵循严格的流程就像使用图书馆一样// 第1步打开文件进入图书馆FILE*fpfopen(book.txt,r);// 第2步检查是否成功找到想要的书架if(fpNULL){printf(无法打开文件\n);return1;}// 第3步读写操作阅读或做笔记charbuffer[100];fgets(buffer,100,fp);// 从文件读取一行// 第4步关闭文件离开图书馆fclose(fp);为什么必须关闭文件释放资源操作系统限制同时打开的文件数量刷新缓冲区确保所有数据都写入磁盘避免数据损坏不关闭文件可能导致数据丢失允许其他程序访问某些系统下文件被一个程序打开时其他程序无法访问文件打开模式详解C语言提供了多种文件打开模式就像不同的图书馆使用规则模式 含义 文件存在 文件不存在 初始位置 类比“r” 只读 打开成功 打开失败 文件开头 只阅读不修改“w” 只写 清空内容 创建新文件 文件开头 新笔记本覆盖旧内容“a” 追加 打开成功 创建新文件 文件末尾 日记本只在末尾添加“r” 读写 打开成功 打开失败 文件开头 可读可写的笔记本“w” 读写 清空内容 创建新文件 文件开头 新笔记本可读可写“a” 读写 打开成功 创建新文件 文件末尾写 文件开头读 日记本可追加写可从头读二进制模式在上述模式后加b如rb、wb等。缓冲区看不见的性能加速器什么是缓冲区缓冲区是内存中的一块区域用于临时存储文件数据减少直接访问磁盘的次数。// 无缓冲区 vs 有缓冲区的区别// 无缓冲每次读写都访问磁盘写字符H→ 访问磁盘 → 写字符e→ 访问磁盘 →...非常慢// 有缓冲批量访问磁盘写字符H→ 缓冲区 → 写字符e→ 缓冲区 →...缓冲区满如4096字节→ 一次性写入磁盘高效缓冲区的三种类型全缓冲缓冲区满时才写入磁盘文件操作默认行缓冲遇到换行符或缓冲区满时写入终端I/O默认无缓冲立即写入标准错误stderr默认手动刷新缓冲区fflush(fp);// 强制将缓冲区内容写入磁盘// 常用于确保日志立即写入防止程序崩溃时丢失数据标准文件指针C语言预置的三个特殊文件C语言自动为每个程序打开三个标准文件FILE*stdin;// 标准输入通常为键盘FILE*stdout;// 标准输出通常为屏幕FILE*stderr;// 标准错误通常为屏幕// 我们熟悉的函数实际使用这些文件指针printf(Hello);// 相当于 fprintf(stdout, Hello);scanf(%d,x);// 相当于 fscanf(stdin, %d, x);fprintf(stderr,Error);// 向标准错误输出有趣的事实在UNIX/Linux系统中你可以重定向这些标准文件./programinput.txt# 从文件读取输入而不是键盘./programoutput.txt# 输出到文件而不是屏幕./program2error.log# 错误信息输出到文件9.1.5 文件系统的幕后故事文件是如何存储在硬盘上的虽然C语言程序员通常不需要关心文件的物理存储但了解基本原理有助于理解某些行为物理存储原理逻辑视图 [文件数据] 连续的一段 物理现实 [块1][块2]...[块N] 分散在磁盘不同位置 通过文件分配表FAT或inode连接起来文件系统的层次结构应用程序 → C标准库 → 操作系统内核 → 文件系统驱动 → 磁盘控制器 → 物理磁盘 (fopen/fread) (系统调用) (管理磁盘块) (硬件接口)文件操作的错误处理常见文件操作错误及原因FILE*fpfopen(data.txt,r);if(fpNULL){// 可能的原因perror(打开文件失败);// 自动显示错误描述// 具体错误码errno// ENOENT: 文件不存在错误号2// EACCES: 权限不足错误号13// EMFILE: 打开文件太多错误号24// ENOSPC: 磁盘空间不足错误号28}完整的错误处理模式FILE*fpfopen(important.dat,r);if(fpNULL){fprintf(stderr,错误无法打开文件 important.dat\n);fprintf(stderr,错误代码%d\n,errno);perror(具体原因);fprintf(stderr,建议检查文件是否存在且具有读取权限\n);returnEXIT_FAILURE;// 返回非零表示失败}文件位置指针文件的书签每个打开的文件都有一个位置指针指示当前读写位置// 初始状态打开文件时位置指针在文件开头模式r、w、r、w// 读取一个字符后位置指针自动后移longcurrent_posftell(fp);// 获取当前位置fseek(fp,0,SEEK_END);// 移动到文件末尾longfile_sizeftell(fp);// 获取文件大小rewind(fp);// 回到文件开头等价于 fseek(fp, 0, SEEK_SET)位置指针的三种基准SEEK_SET从文件开头计算SEEK_CUR从当前位置计算SEEK_END从文件末尾计算9.1.6 实际应用选择正确的文件类型决策树文本文件还是二进制文件开始 │ ├─ 需要人类直接阅读或编辑吗 │ ├─ 是 → 使用文本文件 │ └─ 否 → │ ├─ 需要跨平台兼容吗 │ │ ├─ 是 → 文本文件注意编码 │ │ └─ 否 → │ │ ├─ 存储效率重要吗 │ │ │ ├─ 是 → 二进制文件 │ │ │ └─ 否 → 文本文件更易调试 │ │ └─ │ └─ └─经典案例研究案例1学生成绩管理系统// 方案A文本文件存储CSV格式// students.csv:// 001,张三,85.5// 002,李四,92.0// 优点可直接用Excel打开查看易于调试// 缺点存储效率低解析需要字符串转换// 方案B二进制文件存储// students.dat: [结构体1][结构体2]...structStudent{intid;charname[20];floatscore;};// 优点读写速度快存储紧凑// 缺点人类不可读平台移植需注意结构体对齐案例2游戏存档系统// 混合方案部分数据用文本部分用二进制// savegame.sav:// [二进制头版本信息、校验和]// [二进制数据玩家位置、装备状态等]// [文本部分任务日志、对话记录等]// 优点兼顾性能和可读性性能对比实验让我们进行一个简单的思维实验// 测试存储10000个浮点数floatdata[10000];// 填充随机数...// 方法1文本文件FILE*txt_fpfopen(data.txt,w);for(inti0;i10000;i){fprintf(txt_fp,%f\n,data[i]);// 需要浮点到字符串转换}fclose(txt_fp);// 文件大小约240KB每个数平均24字符// 方法2二进制文件FILE*bin_fpfopen(data.bin,wb);fwrite(data,sizeof(float),10000,bin_fp);// 直接内存拷贝fclose(bin_fp);// 文件大小40KB每个float 4字节// 结果二进制文件大小是文本文件的1/6写入速度快5-10倍9.1.7 现代扩展超越传统文件概念内存映射文件现代操作系统提供了内存映射文件机制允许将文件直接映射到进程的地址空间// 传统文件I/O用户缓冲区 → 内核缓冲区 → 磁盘// 内存映射文件文件区域 → 直接映射到进程地址空间// 优点极大提高大文件访问速度简化随机访问文件锁定机制当多个程序同时访问同一个文件时需要协调// 咨询锁Advisory Lock建议性程序需主动检查// 强制锁Mandatory Lock操作系统强制实施// C标准库没有直接支持需使用平台特定API异步文件I/O传统文件操作是同步的程序等待I/O完成。现代系统支持异步I/O// 同步调用fread() → 等待数据从磁盘读取 → 继续执行// 异步发起读取请求 → 立即继续执行 → 数据准备好后通知程序// 提高程序响应性特别是GUI应用程序总结与展望通过本章的学习你应该已经理解了文件的本质持久存储的数据集合C语言视为字节流文件的重要性让程序拥有记忆实现数据持久化和共享文件的分类文本文件人类可读和二进制文件机器高效C语言文件操作通过文件指针遵循打开→读写→关闭的流程关键概念文件指针、缓冲区、文件位置、错误处理

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询