news 2026/7/7 2:02:02

第五章 标准I/O库

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第五章 标准I/O库

1.流和FILE对象

  • 对于标准I/O库,他们的操作是围绕进行的。
  • 当用标准IO库打开或创建一个文件时,我们已使一个流与一个文件相关联
  • 与标准I/O不同,非标准I/O不使用文件流来读取和写入文件,而是直接操作文件的文件描述符(file descriptor) 。
    非标准I/O通常提供以下函数或接口进行文件操作:
    ·open: 用于打开文件,返回文件描述符。
    ·read:从文件中读取数据。
    ·write: 将数据写入文件。
    ·lseek:设置文件的读写位置。
    ·close: 关闭文件。

标准IO vs. 文件IO(系统调用)

特性标准IO文件IO(系统调用)
接口级别高级,封装了系统调用低级,直接调用内核
操作对象FILE *(流指针)文件描述符(整数,如0, 1, 2, 3...
缓冲自动管理,有三种模式无缓冲,或需要用户自己管理缓冲区
可移植性,符合C标准,不同Unix系统可能有细微差别
性能通常更高,因为缓冲减少了系统调用次数每次调用都是系统调用,上下文切换开销大
控制力相对较弱,抽象程度高极强,可以直接控制设备等

2.缓冲

(1)标准I/O库提供缓冲的目的是尽可能减少使用read和write调用的次数

04-Linux系统编程-第01天(文件IO、阻塞非阻塞) - hh9515 - 博客园

Linux系统编程 42 -系统调用和库函数的比较--预读入缓输出-CSDN博客

  • read、 write 函数常常被称为 Unbuffered I/O。 指的是无用户级缓冲区。 但不保证不使用内核缓冲区。

(2)标准IO提供了三种类型的缓冲

  • 标准I/O缓冲区通常位于运行内存(RAM)中。C标准库使用内存来分配和管理缓冲区。
  • 具体来说,当你打开一个文件流(通过fopen 函数)时,C标准库会为该文件流分配一个缓冲区,并将该缓冲区与文件流相关联。这个缓冲区通常是使用操作系统提供的内存管理函数(如mallo)来动态分配的。操作系统提供了内存分配和释放的机制,C标准库则利用这些机制来为文件流分配所需的内存空间。
  • 文件流的缓冲区大小可以通过函数setvbuf来设置,你可以指定缓冲区的大小或选择使用标准库提供的默认大小。
  • 虽然标准I/O缓冲区位于运行内存中,但它在实际应用中并不直接与物理文件进行读写。相反,标准库将缓冲区作为中间存储区域,当缓冲区被填满或满足一定条件时,数据将从缓冲区复制到操作系统的文件缓存区中,最终才会写入到物理文件中。

(3)标准IO提供了三种类型的缓冲

  • 全缓冲:在这种情况下,当填满标准I/O缓存后才进行实际I/O操作。全缓冲的典型代表是对磁盘文件的读写
  • 行缓冲:当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是键盘输入数据
  • 不带缓冲:也就是不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。

3.打开流

  • fopen:FILE *fopen(const char *filename, const char *mode);
  • fdopen:用于将一个已存在的文件描述符(file descriptor)转换为一个对应的文件流(FILE *)。

4.读和写流

(1)每次读一个字符的IO:getc 或 fgetc

如果流是带缓冲的,可以使用 getc 或 fgetc 函数进行每次一个字符的 I/O 操作。带缓冲的流意味着数据会先被读取到缓冲区,然后一次性操作缓冲区中的数据,可以提高 I/O 的效率。

  • 如果没有禁用流缓冲,默认会使用缓冲区的数据,每次调用 fgetc 都会从缓冲区中获取一个字符。
  • 当缓冲区被耗尽时,会自动从文件中读取更多的数据进行填充。
  • 当缓冲区被耗尽时,文件流会自动从文件中读取更多的数据来填充缓冲区。这样可以避免每次都直接与文件进行 I/O 操作,以提高 I/O 的效率。
  • 默认情况下,标准I/O库会负责管理文件流的缓冲区,确保适当的数据量被从文件中读取到缓冲区中。当程序使用 fgetc 函数等来读取数据时,如果缓冲区中的数据已经被耗尽,标准I/O库会自动将更多数据从文件中读取到缓冲区。
#include <stdio.h> int main() { FILE *file = fopen("example.txt", "r"); if (file == NULL) { perror("文件打开失败"); return -1; } int ch; // 使用 fgetc 逐个字符读取 while ((ch = fgetc(file)) != EOF) { putchar(ch); } fclose(file); return 0; }

(2)每次一行IO:fgets

  • fgets 函数会从文件流 stream 中读取字符,直到达到指定的最大长度 n-1 或者读取到换行符为止(包括换行符),然后将读取的字符串存储到 buffer 中,并在末尾添加 null 字符来表示字符串的结束。

6.二进制IO

  1. fread:用于从文件读取二进制数据
  2. fread:用于从文件读取二进制数据

如何使用二进制 I/O 进行文件读取和写入:

#include <stdio.h> #include <string.h> typedef struct { int id; char name[50]; float score; } Student; // 写入结构体数组到文件 int write_students_to_file(const char *filename) { Student students[] = { {1, "张三", 85.5}, {2, "李四", 92.0}, {3, "王五", 78.5} }; FILE *file = fopen(filename, "wb"); if (!file) { perror("文件打开失败"); return -1; } // 写入整个数组 size_t written = fwrite(students, sizeof(Student), 3, file); printf("成功写入 %zu 个结构体\n", written); fclose(file); return 0; } // 从文件读取结构体数组 int read_students_from_file(const char *filename) { FILE *file = fopen(filename, "rb"); if (!file) { perror("文件打开失败"); return -1; } Student students[3]; size_t read = fread(students, sizeof(Student), 3, file); printf("成功读取 %zu 个结构体\n", read); for (int i = 0; i < read; i++) { printf("学生 %d: ID=%d, 姓名=%s, 分数=%.1f\n", i+1, students[i].id, students[i].name, students[i].score); } fclose(file); return 0; }

二进制 vs 文本 I/O 对比

特性二进制 I/O文本 I/O
数据表示原始字节字符编码
换行符处理不转换系统相关转换
适用场景结构体、图片、音频等文本文件
文件大小精确控制可能因编码而变化
可读性不可直接阅读可直接阅读

二进制IO的问题

  1. 数据类型大小不一致

  2. 填充和对齐问题

  3. 平台兼容性问题(字节序)

暂时记录到这里 2025年12月17日17:17:41

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/7 18:48:48

什么是抖音兴趣电商?抖音小店运营的逻辑是怎么样的?

在数字消费时代的浪潮中&#xff0c;抖音兴趣电商正以革命性的姿态重构传统电商逻辑。当传统电商平台仍停留于“人找货”的搜索购物模式时&#xff0c;抖音凭借其强大的内容生态与算法推荐系统&#xff0c;开创了“货找人”的消费新路径。这种基于用户兴趣的个性化内容推荐机制…

作者头像 李华
网站建设 2026/7/7 1:02:21

2025级C语言第八次周测题解

7-1 电子汪分数 30作者 陈越单位 浙江大学据说汪星人的智商能达到人类 4 岁儿童的水平&#xff0c;更有些聪明汪会做加法计算。比如你在地上放两堆小球&#xff0c;分别有 1 只球和 2 只球&#xff0c;聪明汪就会用“汪&#xff01;汪&#xff01;汪&#xff01;”表示 1 加 2 …

作者头像 李华
网站建设 2026/7/7 16:21:58

你真的会配VSCode远程调试吗?:深入理解SSH端口映射底层原理

第一章&#xff1a;你真的了解VSCode远程调试的本质吗VSCode的远程调试并非简单的代码同步与执行&#xff0c;其核心在于通过SSH、容器或WSL建立一个远程运行时环境&#xff0c;在该环境中启动语言服务器和调试器&#xff0c;并通过VSCode的调试协议&#xff08;如DAP&#xff…

作者头像 李华
网站建设 2026/7/7 6:22:46

DuckDB C++集成开发:终极实践指南与性能优化

DuckDB C集成开发&#xff1a;终极实践指南与性能优化 【免费下载链接】duckdb 项目地址: https://gitcode.com/gh_mirrors/duc/duckdb 你是否正在寻找一种能够无缝嵌入C应用的高性能数据库解决方案&#xff1f;面对传统数据库的复杂依赖和性能瓶颈&#xff0c;DuckDB作…

作者头像 李华
网站建设 2026/7/6 20:16:25

VSCode调试黑科技,一键优化量子机器学习模型参数全过程

第一章&#xff1a;VSCode调试黑科技&#xff0c;一键优化量子机器学习模型参数全过程在量子机器学习领域&#xff0c;模型参数的调优长期依赖复杂的外部工具链和手动迭代。借助 VSCode 的扩展能力与内置调试器&#xff0c;开发者现在可以实现从参数初始化到梯度评估的一键式自…

作者头像 李华
网站建设 2026/7/7 17:38:40

【独家披露】IBM Quantum官方推荐的VSCode开发配置与示例代码

第一章&#xff1a;量子算法的 VSCode 示例代码 在现代量子计算开发中&#xff0c;Visual Studio Code&#xff08;VSCode&#xff09;已成为主流集成开发环境之一。借助 Q#、Qiskit 等量子编程框架的扩展支持&#xff0c;开发者可在本地快速构建、模拟和调试量子算法。 配置开…

作者头像 李华