嵌入式Linux系统编程 — 2.1 标准I/O库简介

目录

1 标准I/O库简介

1.1 标准I/O库简介

1.2 标准 I/O 和文件 I/O 的区别

2 FILE 指针

3 标准I/O库的主要函数简介

4 标准输入、标准输出和标准错误

4.1 标准输入、标准输出和标准错误概念

4.2 示例程序

5 打开文件fopen()

5.1 fopen()函数简介

5.2 新建文件的权限

5.3 示例程序

6 fread()和fwrite()读文件和写文件

6.1 fread()和fwrite()简介

6.2 示例程序

7 fseek()定位

7.1 fseek()函数简介

7.2 示例程序


1 标准I/O库简介

1.1 标准I/O库简介

Linux系统中的标准I/O库是C语言标准库的一个关键组成部分,它提供了一套丰富的函数接口,用于执行文件的输入输出操作。这些函数定义在<stdio.h>头文件中,包括打开和关闭文件、读取和写入数据、格式化输入输出等。由于标准I/O是C语言标准的一部分,因此使用标准I/O库编写的程序具有良好的可移植性。

1.2 标准 I/O 和文件 I/O 的区别

  • 虽然标准 I/O 和文件 I/O 都是 C 语言函数,但是标准 I/O 是标准 C 库函数,而文件 I/O 则是 Linux系统调用;
  • 标准 I/O 是由文件 I/O 封装而来,标准 I/O 内部实际上是调用文件 I/O 来完成实际操作的;
  • 可移植性:标准 I/O 相比于文件 I/O 具有更好的可移植性,通常对于不同的操作系统,其内核向应用层提供的系统调用往往都是不同,譬如系统调用的定义、功能、参数列表、返回值等往往都是不一样的;而对于标准 I/O 来说,由于很多操作系统都实现了标准 I/O 库,标准 I/O 库在不同的操作系统之间其接口定义几乎是一样的,所以标准 I/O 在不同操作系统之间相比于文件 I/O 具有更好的可移植性。
  • 性能、效率: 标准 I/O 库在用户空间维护了自己的 stdio 缓冲区, 所以标准 I/O 是带有缓存的,而文件 I/O 在用户空间是不带有缓存的,所以在性能、效率上,标准 I/O 要优于文件 I/O。

2 FILE 指针

FILE 指针的作用相当于文件描述符,只不过 FILE 指针用于标准 I/O 库函数中、而文件描述符则用于文件I/O 系统调用中。

文件 I/O 函数都是围绕文件描述符进行的,当调用 open()函数打开一个文件时,即返回一个文件描述符 fd,然后该文件描述符就用于后续的 I/O 操作。而对于标准 I/O 库函数来说,它们的操作是围绕 FILE 指针进行的,当使用标准 I/O 库函数打开或创建一个文件时,会返回一个指向 FILE 类型对象的指针(FILE *) ,使用该 FILE 指针与被打开或创建的文件相关联,然后该 FILE 指针就用于后续的标准 I/O 操作。

FILE指针是C语言标准库中用于处理文件输入输出的一种数据类型。它指向FILE结构体的一个实例,这个结构体包含了执行文件操作所需的各种信息,如文件缓冲区、文件状态标志、错误标志以及指向文件当前位置的指针等。

3 标准I/O库的主要函数简介

(1) 打开文件

fopen(const char *filename, const char *mode)
  • filename:要打开的文件的名称。
  • mode:打开文件的模式,如"r"(只读),"w"(只写,会覆盖文件),"a"(追加),"r+"(读写)等。

(2) 关闭文件

fclose(FILE *stream)
  • stream:要关闭的文件的指针。

(3) 读取文件

fread(void *ptr, size_t size, size_t count, FILE *stream)
  • ptr:指向用于存储读取数据的缓冲区的指针。
  • size:每个数据项的大小(以字节为单位)。
  • count:要读取的数据项数量。
  • stream:指向包含要读取数据的文件的指针。

(4) 写入文件

fwrite(const void *ptr, size_t size, size_t count, FILE *stream)
  • ptr:指向要写入的数据的缓冲区的指针。
  • size:每个数据项的大小(以字节为单位)。
  • count:要写入的数据项数量。
  • stream:指向包含目标文件的指针。

(5) 从文件中读取一个字符

fgetc(FILE *stream)
  • stream:指向包含要读取字符的文件的指针。

(6) 从文件中读取一个字符

fputc(int c, FILE *stream)
  • c:要写入的字符(作为int类型传递)。
  • stream:指向包含目标文件的指针。

 (7) 从文件中读取一行字符串

fgets(char *str, int num, FILE *stream)
  • str:指向用于存储读取字符串的缓冲区的指针。
  • num:最大字符数,包括空字符'\0'。
  • stream:指向包含要读取数据的文件的指针。

 (8) 向文件写入一个字符串

fputs(const char *str, FILE *stream)
  • str:要写入的字符串。
  • stream:指向包含目标文件流的指针。

 (9) 输出数据

fprintf(FILE *stream, const char *format, ...)
  • stream:指向包含目标文件的指针。
  • format:格式字符串,定义了后续参数的输出格式。
  • ...:要输出的数据。

 (10) 检测文件是否到达文件末尾

feof(FILE *stream)
  • stream:指向要检查的文件的指针。

 (11) 检查文件流是否发生了错误

ferror(FILE *stream)
  • stream:指向要检查的文件的指针。

4 标准输入、标准输出和标准错误

4.1 标准输入、标准输出和标准错误概念

用户通过标准输入设备与系统进行交互, 进程将从标准输入(stdin)文件中得到输入数据,将正常输出数据(譬如程序中 printf 打印输出的字符串) 输出到标准输出(stdout) 文件,而将错误信息(譬如函数调用报错打印的信息)输出到标准错误(stderr) 文件。

在Linux系统中,标准输入(stdin)、标准输出(stdout)和标准错误(stderr)是进程与其环境之间通信的三种基本方式。它们是文件描述符,分别对应文件描述符0、1和2。下面是它们各自的功能:

标准输入(stdin)

  • 文件描述符:0
  • 功能:允许用户将输入数据发送给正在运行的程序。
  • 来源:通常是键盘输入,但也可以是重定向自文件、管道等。

标准输出(stdout)

  • 文件描述符:1
  • 功能:程序的输出结果默认发送到标准输出。
  • 去向:通常是终端或控制台(例如计算机所连接的显示器)。

标准错误(stderr)

  • 文件描述符:2
  • 功能:用于发送错误消息或诊断信息。
  • 去向:默认也是终端或控制台,但与标准输出分开,使得错误信息可以独立于正常输出被处理或重定向。

4.2 示例程序

下面的简单的示例程序会从标准输入读取一行文本,然后将这行文本通过标准输出打印出来,并同时将一个错误消息通过标准错误输出。

#include <stdio.h>
#include <string.h>int main() {char buffer[1024]; // 缓冲区,用于存储输入// 从标准输入读取一行文本printf("请输入一些文本:");fgets(buffer, sizeof(buffer), stdin); // 使用fgets从stdin读取// 将读取的文本通过标准输出打印printf("你输入的是:%s", buffer);// 检查输入的文本中是否包含空格if (strchr(buffer, ' ') != NULL) {// 如果包含空格,通过标准错误输出错误信息fprintf(stderr, "错误:输入的文本中包含空格。\n");}return 0;
}

在这个程序中:

  • stdinstdoutstderrstdio.h头文件中定义的宏,分别代表标准输入、标准输出和标准错误的文件指针。
  • fgets函数用于从stdin读取一行文本,直到遇到换行符或缓冲区满。它将文本存储在buffer数组中。
  • printf函数将读取的文本通过stdout打印到终端。
  • 使用strchr函数来检查输入的字符串中是否包含空格。如果strchr返回非空指针,表示输入中包含空格,程序通过stderr输出错误信息。

5 打开文件fopen()

5.1 fopen()函数简介

在文件 I/O 中,使用 open()系统调用打开或创建文件,而在标准 I/O 中,我们将使用库函数fopen()打开或创建文件, fopen()函数原型如下所示:

#include <stdio.h>FILE *fopen(const char *path, const char *mode);
  • path: 参数 path 指向文件路径,可以是绝对路径、也可以是相对路径。
  • mode: 参数 mode 指定了对该文件的读写权限,如下所示。
mode说明对应于 open()函数的 flags 参数取值
r以只读方式打开文件。O_RDONLY
r+以可读、可写方式打开文件。O_RDWR
w以只写方式打开文件,如果参数 path 指定的文件存在,将文件长度截断为 0;如果指定文件不存在则创建该文件。O_WRONLY | O_CREAT | O_TRUNC
w+以可读、可写方式打开文件,如果参数 path 指定的文件存在,将文件长度截断为 0;如果指定文件不存在则创建该文件。O_RDWR | O_CREAT | O_TRUNC
a以只写方式打开文件,打开以进行追加内容(在文件末尾写入),如果文件不存在则创建该文件。O_WRONLY | O_CREAT | O_APPEND
a+以可读、可写方式打开文件,以追加方式写入(在文件末尾写入),如果文件不存在则创建该文件。O_RDWR | O_CREAT | O_APPEND
  • 返回值: 调用成功返回一个指向 FILE 类型对象的指针(FILE *),该指针与打开或创建的文件相关联,后续的标准 I/O 操作将围绕 FILE 指针进行。 如果失败则返回 NULL,并设置 errno 以指示错误原因。

5.2 新建文件的权限

fopen()只有两个参数 path 和 mode,不同于 open()系统调用,它并没有任何一个参数来指定新建文件的权限。 当参数 mode 取值为"w"、 "w+"、 "a"、 "a+"之一时,如果参数 path 指定的文件不存在,则会创建该文件。

虽然调用 fopen()函数新建文件时无法手动指定文件的权限,但却有一个默认值:

S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH (0666)

5.3 示例程序

#include <stdio.h>int main() {FILE *file = fopen("example.txt", "w");if (file == NULL) {perror("Error opening file");return 1;}fprintf(file, "Hello, World!\n");fclose(file); // 记得关闭文件return 0;
}

示例代码中,以写入模式打开example.txt文件。如果文件打开失败,fopen()将返回NULL,通过perror()函数输出错误信息。成功打开文件后,使用fprintf()向文件写入内容,并最终使用fclose()关闭文件。运行的结果如下:

6 fread()和fwrite()读文件和写文件

6.1 fread()和fwrite()简介

库函数中使用 fread()用于读取文件数据,函数原型如下所示:

#include <stdio.h>size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
  • ptr: fread()将读取到的数据存放在参数 ptr 指向的缓冲区中;
  • size: fread()从文件读取 nmemb 个数据项,每一个数据项的大小为 size 个字节,所以总共读取的数据大小为 nmemb * size 个字节。
  • nmemb: 参数 nmemb 指定了读取数据项的个数。
  • stream: FILE 指针。
  • 返回值: 调用成功时返回读取到的数据项的数目(数据项数目并不等于实际读取的字节数,除非参数size 等于 1);如果发生错误或到达文件末尾,则 fread()返回的值将小于参数 nmemb,那么到底发生了错误还是到达了文件末尾, fread()不能区分文件结尾和错误, 究竟是哪一种情况,此时可以使用 ferror()或 feof()函数来判断。

库函数中使用 fwrite()将数据写入到文件中,函数原型如下所示:

#include <stdio.h>size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
  • ptr: 将参数 ptr 指向的缓冲区中的数据写入到文件中。
  • size: 参数 size 指定了每个数据项的字节大小,与 fread()函数的 size 参数意义相同。
  • nmemb: 参数 nmemb 指定了写入的数据项个数,与 fread()函数的 nmemb 参数意义相同。
  • stream: FILE 指针。
  • 返回值: 调用成功时返回写入的数据项的数目(数据项数目并不等于实际写入的字节数,除非参数 size等于 1);如果发生错误,则 fwrite()返回的值将小于参数 nmemb(或者等于 0)。

6.2 示例程序

下面代码演示了如何在C语言中使用标准I/O函数fopenfwriterewindfreadfclose来执行文件的基本读写操作。

#include <stdio.h>
#include <stdlib.h>int main() {const char *filename = "example.txt";char buffer[] = "Hello, World!";char readBuffer[sizeof(buffer)];// 打开文件用于写入和读取FILE *fp = fopen(filename, "w+");if (fp == NULL) {perror("Error opening file");return 1;}// 写入数据到文件if (fwrite(buffer, 1, sizeof(buffer), fp) != sizeof(buffer)) {fclose(fp);perror("Error writing to file");return 1;}// 移动文件指针到文件开头,准备读取rewind(fp);// 从文件读取数据if (fread(readBuffer, 1, sizeof(buffer), fp) != sizeof(buffer)) {fclose(fp);perror("Error reading from file");return 1;}// 确保字符串以空字符结尾readBuffer[sizeof(buffer) - 1] = '\0';// 打印读取的数据printf("Read from file: %s\n", readBuffer);// 关闭文件fclose(fp);return 0;
}

程序首先以读写模式打开一个名为"example.txt"的文件,然后向其中写入字符串"Hello, World!"。之后,程序将文件指针重置到文件开头,从文件中读取相同数量的数据到一个缓冲区,并确保字符串以空字符结尾,最后打印读取的字符串并关闭文件。程序还包括了基本的错误检查,以确保文件操作成功完成。程序运行结果如下:

 

7 fseek()定位

7.1 fseek()函数简介

库函数 fseek()的作用类似于系统调用 lseek(), 用于设置文件读写位置偏移量, lseek()用于文件 I/O,而库函数 fseek()则用于标准 I/O,其函数原型如下所示:

#include <stdio.h>int fseek(FILE *stream, long offset, int whence);
  • stream: FILE 指针。
  • offset: 与 lseek()函数的 offset 参数意义相同。
  • whence: 与 lseek()函数的 whence 参数意义相同。
  • 返回值: 成功返回 0;发生错误将返回-1,并且会设置 errno 以指示错误原因; 与 lseek()函数的返回值意义不同,这里要注意!

7.2 示例程序

如下程序如何使用fseek()来设置文件读写位置偏移量。

#include <stdio.h>
#include <stdlib.h>int main() {const char *filename = "input.txt";char buffer[1024];int i;// 打开文件用于写入FILE *file = fopen(filename, "w");if (file == NULL) {perror("Error opening file for writing");return 1;}// 提示用户输入文本printf("Enter your text (max 1024 characters): ");fgets(buffer, sizeof(buffer), stdin); // 从标准输入读取一行文本// 写入文本到文件fputs(buffer, file);// 关闭文件fclose(file);// 重新打开文件用于读取file = fopen(filename, "r");if (file == NULL) {perror("Error opening file for reading");return 1;}// 移动文件指针到文件开头fseek(file, 4, SEEK_SET);// 读取文件内容while (fgets(buffer, sizeof(buffer), file) != NULL) {printf("Read from file: %s", buffer);}// 关闭文件fclose(file);return 0;
}

代码创建了一个名为"input.txt"的文件,并提示用户输入一段文本。输入的文本被写入到文件中,然后程序重新打开文件跳过前4个字节,并读取剩余的内容,将其打印到屏幕上。如果文件操作过程中出现错误,程序将显示错误信息并退出。运行结果如下:

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ezsql(buuctf加固题)

开启环境 SSH连接 第一个为页面地址WEB服务 or 11# 利用万能密码登录 密码可以随便输入或者不输入 这里就可以判断这个题目是让我们加固这个登录页面 防止sql注入 查看index.php 添加以下代码 $username addslashes($username); $password addslashes($password);…

RK3588+FPGA+算能BM1684X:高性能AI边缘计算盒子,应用于视频分析、图像视觉等

搭载RK3588&#xff08;四核 A76四核 A55&#xff09;&#xff0c;CPU主频高达 2.4GHz &#xff0c;提供1MB L2 Cache 和 3MB L3 &#xff0c;Cache提供更强的 CPU运算能力&#xff0c;具备6T AI算力&#xff0c;可扩展至38T算力。 产品规格 系统主控CPURK3588&#xff0c;四核…

FactoryTalk View Site Edition的VBA基本应用

第一节 在VBA中标签的读取和写入 本例要达到的目标是通过FactoryTalk View Site Edition&#xff08;以下简称SE&#xff09;的VBA来访问PLC中的下位标签&#xff0c;并实现标签的读写。 1.准备工作 打开SE&#xff0c;选择应用程序类型&#xff08;本例是Site Edition Netwo…

后端进阶-分库分表

文章目录 为什么需要分库为什么需要分表 什么时候需要分库分表只需要分库只需要分表 分库分表解决方案垂直分库水平分库垂直分表水平分表 分库分表常用算法范围算法hash分片查表分片 分库分表模式客户端模式代理模式 今天跟着训练营学习了分库分表&#xff0c;整理了学习笔记。…

【Linux】进程(8):Linux真正是如何调度的

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解Linux进程&#xff08;8&#xff09;&#xff1a;Linux真正是如何调度的&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 之前我们讲过&#xff0c;在大…

[ubuntu18.04]搭建mptcp测试环境说明

MPTCP介绍 Multipath TCP — Multipath TCP -- documentation 2022 documentation 安装ubuntu18.04&#xff0c;可以使用虚拟机安装 点击安装VMware Tool 桌面会出现如下图标 双击打开VMware Tools&#xff0c;复制如下图所示的文件到Home目录 打开终端&#xff0c;切换到管…

C++结合ffmpeg获取声音的分贝值

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、分贝是什么&#xff1f;1.功率量2.场量 二、实际操作1.分析wav文件2.读取麦克风 总结 前言 最近面对一个需求&#xff0c;就是需要传递声音文件到模型里推…

CTFHUB-技能树-web-信息泄露

目录 1.目录遍历 2.PHPINFO 3.备份文件下载 3.1 网站源码 3.2 bak文件 3.3 vim缓存 3.4 .DS_Store 4.Git泄露 4.1 Log 4.2 Stash 4.3 Index 5.SVN泄露 6.HG泄露 1.目录遍历 这个没什么好讲的&#xff0c;进去直接点击找flag,然后在下面目录翻&#xff0c;就找到了 …

【Vue】路由介绍

一、引入 思考 单页面应用程序&#xff0c;之所以开发效率高&#xff0c;性能好&#xff0c;用户体验好 最大的原因就是&#xff1a;页面按需更新 比如当点击【发现音乐】和【关注】时&#xff0c;只是更新下面部分内容&#xff0c;对于头部是不更新的 要按需更新&#xff…

mysql 8 linux7,8安装教程

选择自己对应的linux版本 cat /etc/os-release //查看自己linux系统版本 1.mysql下载地址 MySQL :: Download MySQL Community Server (Archived Versions) 拉到下面找到 选择自己linux指定的版本&#xff0c;否则会很麻烦 cat /etc/os-release //查看系统版本 2.查…

抱抱脸上第一的开原模型Qwen2-72B;腾讯开源人像照片生成视频的模型;Facebook开源翻译模型;智谱 AI 推出的最新一代预训练模型

✨ 1: Qwen2 Qwen2 是一种多语言预训练和指令调优的语言模型&#xff0c;支持128K上下文长度并在多项基准测试中表现优异。 Qwen2&#xff08;全称“Qwen Qwen”&#xff0c;简称Qwen&#xff09;是一个先进的大语言模型家族&#xff0c;在其前身Qwen1.5的基础上进行了重大提…

读取文件

自学python如何成为大佬(目录):自学python如何成为大佬(目录)_利用python语言智能手机的默认语言实战一-CSDN博客 在Python中打开文件后&#xff0c;除了可以向其写入或追加内容&#xff0c;还可以读取文件中的内容。读取文件内容主要分为以下几种情况&#xff1a; 1 读取指…

【人工智能】流行且重要的智能算法整理

✍&#x1f3fb;记录学习过程中的输出&#xff0c;坚持每天学习一点点~ ❤️希望能给大家提供帮助~欢迎点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;指点&#x1f64f; 小记&#xff1a; 今天在看之前写的文档时&#xff0c;发现有人工智能十大算法的内容&#xf…

wireshark 二次开发

一、 Windows 准备 1、源代码下载 Git&#xff1a;https://github.com/wireshark/wireshark 2、 准备Visual C 要编译wireshark&#xff0c;开发电脑上应该安装了Visual Studio并包括了Visual C&#xff0c;请至少安装Visual Studio 2010以减少不必要的麻烦。 visual studio …

【ffmpeg】本地格式转换 mp4转wav||裁剪mp4

个人感受&#xff1a;太爽了&#xff01;&#xff01;&#xff01;&#xff08;可能用惯了转换网站和无良的转换软件&#xff09; ———— 使用FFmpeg把mp4文件转换为WAV文件 - 简书 (jianshu.com) FFMPEG 视频分割和合并 - 简书 (jianshu.com) ———— 示例 ffmpeg -i …

具有 MOSFET 的电压到电流 (V-I) 转换器电路

设计说明 该单电源、低侧、V-I 转换器向可以连接到比运算放大器电源电压更高的电压的负载提供经过良好调节的电流。该 电路接受介于 0V 和 2V 之间的输入电压&#xff0c;将其转换为介于 0mA 和 100mA 之间的电流。通过将低侧电流检测电 阻 R3 上的压降反馈到运算放大器的反相…

C语言 指针——函数指针的典型应用:通用排序

目录 编程实现升序和降序排序 如果不使用函数指针编程… 使用函数指针编写一个通用的排序函数 小结 编程实现升序和降序排序 如果不使用函数指针编程… 使用函数指针编写一个通用的排序函数 小结 正确理解指针的概念  指针是一种特殊的数据类型  指针类型的变量&am…

【多模态】37、TextSquare | 借助 Gemini-Pro 通过四个步骤来生成高质量的文本问答数据

文章目录 一、背景二、方法2.1 Square-10M2.2 模型结构2.3 使用 Square-10M 进行有监督微调 三、效果3.1 实验设置3.2 Benchmark 测评 论文&#xff1a;TextSquare: Scaling up Text-Centric Visual Instruction Tuning 代码&#xff1a;暂无 出处&#xff1a;字节 | 华中科技…

自动驾驶仿真(高速道路)LaneKeeping

前言 A high-level decision agent trained by deep reinforcement learning (DRL) performs quantitative interpretation of behavioral planning performed in an autonomous driving (AD) highway simulation. The framework relies on the calculation of SHAP values an…

WPF国际化的最佳实践

WPF国际化的最佳实践 1.创建项目资源文件 如果你的项目没有Properties文件夹和Resources.resx文件&#xff0c;可以通过右键项目-资源-常规-添加创建或打开程序集资源 2.添加国际化字符串 打开Resources.resx文件&#xff0c;添加需要翻译的文本字符&#xff0c;并将访问修…