P5 Linux 标准C库函数

news2024/11/27 10:30:00

目录

前言

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

02 打开文件 fopen()

03 新建文件的权限

04 fclose()关闭文件

05 读文件和写文件

06 库函数 fseek 定位

6.1 lseek的使用

07 ftell()函数


前言

                                

🎬 个人主页:@ChenPi

🐻推荐专栏1: 《C++_@ChenPi的博客-CSDN博客》✨✨✨ 

🔥 推荐专栏2: 《Linux C应用编程(概念类)_@ChenPi的博客-CSDN博客》✨✨✨

🛸推荐专栏3: ​​​​​​《 链表_@ChenPi的博客-CSDN博客 》 ✨✨✨
🌺本篇简介  :  上一章我们学了系统调用,open,read,write,lseek等等,这章我们学习一下C库函数的open,read,write函数

在Linux环境下,个人平时还是使用系统调用多一些,但相对于说可移值性来说,还是C库函数好,

而且相关的API还会多些

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

  1. 标准输入设备指的就是计 算机系统的标准的输入设备,通常指的是计算机所连接的键盘;
  2. 标准输出设备指的是计算机系统中用于 输出标准信息的设备,通常指的是计算机所连接的显示器
  3. 标准错误设备则指的是计算机系统中用于显示 错误信息的设备,通常也指的是显示器设备。

每个进程启动之后都会默认打开标准输入、标准输出以及标准错误,得到三个文件描述符

STDIN_FILENO    0 代表标准输入
STDOUT_FILENO   1 代表标准输出
STDERR_FILENO   2 代表标准错误

分别代表 0、1、2,这些宏定义在 unistd.h 头文件中:

/* Standard file descriptors. */ 
#define STDIN_FILENO 0 /* Standard input. */ 
#define STDOUT_FILENO1 /* Standard output. */ 
#define STDERR_FILENO 2 /* Standard error output. */ 


0、1、2 这三个是文件描述符,只能用于文件 I/O(read()、write()等),那么在标准 I/O 中,自然是无 法使用文件描述符来对文件进行 I/O 操作的,它们需要围绕 FILE 类型指针来进行,在 stdio.h 头文件中有相 应的定义,如下:

/* Standard streams. */ 
extern struct _IO_FILE *stdin; /* Standard input stream. */ 
extern struct _IO_FILE *stdout; /* Standard output stream. */ 
extern struct _IO_FILE *stderr; /* Standard error output stream. */ 
/* C89/C99 say they're macros. Make them happy. */ 
#define stdin stdin 
#define stdout stdout 
#define stderr stderr 

Tips:struct _IO_FILE 结构体就是 FILE 结构体,使用了 typedef 进行了重命名。

所以,在标准 I/O 中,可以使用 stdin、stdout、stderr 来表示标准输入、标准输出和标准错误。

02 打开文件 fopen()

在 0 所介绍的文件 I/O 中,使用 open()系统调用打开或创建文件

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

#include <stdio.h> 
 
FILE *fopen(const char *path, const char *mode); 

函数参数和返回值含义如下:

  1. path:参数 path 指向文件路径,可以是绝对路径、也可以是相对路径。
  2. mode:参数 mode 指定了对该文件的读写权限,是一个字符串,稍后介绍。
  3. 返回值:调用成功返回一个指向 FILE 类型对象的指针(FILE *),该指针与打开或创建的文件相关联, 后续的标准 I/O 操作将围绕 FILE 指针进行。如果失败则返回 NULL,并设置 errno 以指示错误原因

参数 mode 字符串类型,可取值为如下值之一: 

mode参数取值

  • r 以只读方式打开文件。
  • r+ 以可读、可写方式打开文件。
  • w 以只写方式打开文件,如果参数 path 指定的文件 存在,将文件长度截断为 0;如果指定文件不存在 则创建该文件。
  • w+ 以可读、可写方式打开文件,如果参数 path 指定 的文件存在,将文件长度截断为 0;如果指定文件 不存在则创建该文件。
  • a 以只写方式打开文件,打开以进行追加内容(在 文件末尾写入),如果文件不存在则创建该文 件。
  • a +以可读、可写方式打开文件,以追加方式写入 (在文件末尾写入),如果文件不存在则创建该 文件。


03 新建文件的权限


由 fopen()函数原型可知,fopen()只有两个参数 path 和 mode,

不同于 open()系统调用,它并没有任何一 个参数来指定新建文件的权限。

当参数 mode 取值为"w"、"w+"、"a"、"a+"之一时,如果参数 path 指定的文 件不存在

则会创建该文件,

那么新的文件的权限是如何确定的呢?

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

S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH (0666)
使用示例

  1. 使用只读方式打开文件: fopen(path, "r");
  2. 使用可读、可写方式打开文件: fopen(path, "r+");
  3. 使用只写方式打开文件,并将文件长度截断为 0,如果文件不存在则创建该文件:fopen(path, "w");


04 fclose()关闭文件

调用 fclose()库函数可以关闭一个由 fopen()打开的文件,其函数原型如下所示:

#include <stdio.h> 
 
int fclose(FILE *stream); 


参数 stream 为 FILE 类型指针,调用成功返回 0;失败将返回 EOF(也就是-1),并且会设置 errno 来 指示错误原因。

05 读文件和写文件

 fread()和 fwrite()库函数

对文件进行读、写操 作了,函数原型如下所示:

#include <stdio.h> 
 
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); 

库函数 fread()
用于读取文件数据,其参数和返回值含义如下:

  1. ptr:fread()将读取到的数据存放在参数 ptr 指向的缓冲区中;
  2. size:fread()从文件读取 nmemb 个数据项,每一个数据项的大小为 size 个字节,所以总共读取的数据大 小为 nmemb * size 个字节。
  3. nmemb:参数 nmemb 指定了读取数据项的个数。
  4. stream:FILE 指针。
  5. 返回值:调用成功时返回读取到的数据项的数目(数据项数目并不等于实际读取的字节数,除非参数size 等于 1);

库函数 fwrite()
用于将数据写入到文件中,其参数和返回值含义如下: 

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

由此可知,库函数 fread()、fwrite()中指定读取或写入数据大小的方式与系统调用 read()、write()不同, 前者通过 nmemb(数据项个数)*size(每个数据项的大小)的方式来指定数据大小,而后者则直接通过一 个 size 参数指定数据大小。 

06 库函数 fseek 定位

库函数 fseek()则用于标准 I/O,其函数原型如下所示:

#include <stdio.h> 
 
int fseek(FILE *stream, long offset, int whence); 

函数参数和返回值含义如下: stream:FILE 指针。

  1. offset:与 lseek()函数的 offset 参数意义相同。
  2. whence:与 lseek()函数的 whence 参数意义相同。
  3. 返回值:成功返回 0;发生错误将返回-1,并且会设置 errno 以指示错误原因;与 lseek()函数的返回值 意义不同,这里要注意!

调用库函数 fread()、fwrite()读写文件时,文件的读写位置偏移量会自动递增,使用 fseek()可手动设置 文件当前的读写位置偏移量。 

6.1 lseek的使用

  1. 譬如将文件的读写位置移动到文件开头处: fseek(file, 0, SEEK_SET);
  2. 将文件的读写位置移动到文件末尾: fseek(file, 0, SEEK_END);
  3. 将文件的读写位置移动到 100 个字节偏移量处: fseek(file, 100, SEEK_SET);
fread,fwrite,fseek综合小案例 
#include <stdio.h> 
#include <stdlib.h> 
 
 
int main(void) 
 
{ 
 FILE *fp = NULL; 
 char rd_buf[100] = {0}; 
 char wr_buf[] = "hello world"; 
 int ret; 
 
 /* 打开文件 */ 
 if (NULL == (fp = fopen("./test_file", "w+"))) { 
 perror("fopen error"); 
 exit(-1); 
 } 
 printf("文件打开成功!\n"); 
 
 /* 写文件 */ 
 if (sizeof(wr_buf) > 
 fwrite(wr_buf, 1, sizeof(wr_buf), fp)) { 
 
 printf("fwrite error\n"); 
 fclose(fp); 
 exit(-1); 
 } 
 printf("数据写入成功!\n"); 
 
 /* 将读写位置移动到文件头部 */ 
 if (0 > fseek(fp, 0, SEEK_SET)) { 
 perror("fseek error"); 
 fclose(fp); 
 exit(-1); 
 } 
 
 /* 读文件 */ 
 if (sizeof(wr_buf) > 
 (ret = fread(rd_buf, 1, sizeof(wr_buf), fp))) { 
 printf("fread error\n"); 
 fclose(fp); 
 exit(-1); 
 } 
 
 printf("成功读取%d 个字节数据: %s\n", ret, rd_buf); 
 
 /* 关闭文件 */ 
 fclose(fp); 
 exit(0); 
 
}

07 ftell()函数

库函数 ftell()可用于获取文件当前的读写位置偏移量,其函数原型如下所示:

#include <stdio.h> 
 
long ftell(FILE *stream); 


参数 stream 指向对应的文件,函数调用成功将返回当前读写位置偏移量;调用失败将返回-1,并会设置errno 以指示错误原因。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

sql 读写注入

root高权限读写注入 load_file 读取文件 大姐我真是整了半天都是nullnullnull缝子 结果看了半天这个my.ini是被隐藏的大哥 load_file()读取文件结果为null_mysql load_file返回null解决办法_黑小薛的博客-CSDN博客 终于读出来了 此时参数值系统变量 secure_file_priv已经被修…

使用DevEco Studio时遇见的错误情况与问题

第一个 问题:打开项目文件,控制台报错 hvigor ERROR: Unable to find sdk.dir in local.properties or OHOS_BASE_SDK_HOME in the system environment path. 解决办法:在项目根目录中打开local.properties。如果没有local.properties,自己创建。 在local.properties中填…

[ROS2] --- 手动编写一个节点

1 准备工作 1.1 创建/编译工作空间 创建工作空间 mkdir -p ~/dev_ws/src cd ~/dev_ws/src1. 2 创建功能包 ros2 pkg create learning01_write_a_node --build-type ament_cmake --dependencies rclcpp可以看到目录结构如下&#xff1a; 1. 3 创建节点 在learing01_write…

234 回文链表

解题思路&#xff1a; \qquad 由于链表的结构特点&#xff0c;访问链表中的元素的时间复杂度为O(n)。相比较而言&#xff0c;使用数组会方便很多&#xff0c;实现O(1)访问。 \qquad 所以这个题&#xff0c;可以先遍历一遍把数值存到数组中&#xff0c;再使用双指针判断是否是…

【Kubernetes】可视化UI界面Dashboard

安装和配置k8s可视化UI界面 一、安装Dashboard1.1、上传镜像并解压1.2、安装dashboard组件1.3、修改service1.4、访问dashboard 二、通过Token令牌访问Dashboard2.1、创建clusterrolebinding2.2、获取token2.3、使用token登录 三、通过kubeconfig文件访问Dashboard3.1、创建clu…

音视频技术开发周刊 | 322

每周一期&#xff0c;纵览音视频技术领域的干货。 新闻投稿&#xff1a;contributelivevideostack.com。 超级AI不会主宰人类&#xff0c;但人工智能必须开源&#xff01;LeCun最新采访引全网300万人围观 LeCun最新访谈视频中&#xff0c;再次坦露了自己对开源AI的看法。超级AI…

面试 Java 框架八股文十问十答第二期

面试 Java 框架八股文十问十答第二期 作者&#xff1a;程序员小白条&#xff0c;个人博客 相信看了本文后&#xff0c;对你的面试是有一定帮助的&#xff01; ⭐点赞⭐收藏⭐不迷路&#xff01;⭐ 1.AOP的术语&#xff0c;以及两种动态代理实现方法&#xff0c;以及它们的区别…

“快慢指针”思想在物理或者逻辑循环中的应用

1 基础概念 1.1 什么是物理循环和逻辑循环&#xff1f; 物理循环是指物理索引访问顺序上相邻&#xff0c;逻辑上也相邻&#xff0c;比如循环链表&#xff0c;逻辑循环则指物理的索引上不一定相邻 1.2 快慢指针本质上可以解决逻辑循环问题&#xff0c;而物理循环也属于逻辑循…

MCS-51系列与AT89C5x系列单片机的介绍与AT系列的命名规则

MCS-51系列与AT89C5x系列单片机 主要涉及MCS-51系列与AT89C5x系列单片机的介绍与AT系列单片机的命名规则 文章目录 MCS-51系列与AT89C5x系列单片机一、 MCS-51系列单片机二、AT89C5x系列单片机2.1 AT89C5x/AT89S5x系列单片机的特点2.2 AT89系列单片机的型号说明2.2.1 前缀2.2.2…

握这些员工管理技巧,助你打造高效团队!

人力资源是一个组织中至关重要的一环&#xff0c;而员工管理是确保团队高效运转的关键因素之一。一个优秀的经理需要具备多方面的技巧和能力&#xff0c;以便激发员工的潜力&#xff0c;促进合作和增加团队的效率。在这里&#xff0c;我将分享一些实用的员工管理技巧&#xff0…

使用肘部法则选择KMeans聚类中的k值

在这篇文章中&#xff0c;我们将讨论如何选择最好的k&#xff08;聚类数&#xff09;的k-Means聚类算法。 肘部法则简介 任何无监督算法的基本步骤是确定数据可以被聚类到的聚类的最佳数量。因为我们在无监督学习中没有任何预定义数量的聚类。我们倾向于使用一些可以帮助我们…

sar命令详解

sar是强大的linux系统活动状况收集、报告命令。可以收集CPU&#xff0c;内存&#xff0c;磁盘I/O&#xff0c;网络等诸多数据。对于性能分析是个可靠的利器。 安装 sar命令是sysstat下的一个工具&#xff0c;所以安装sar需要首先安装sysstat命令&#xff0c;可以考虑yum安装或…

UE Windows平台下Linux的交叉编译项目打包

UE Windows平台下Linux的交叉编译项目打包 交叉编译&#xff08;Cross-compilation&#xff09; 使得在以Windows为中心的工作流程中工作的游戏开发者能够以Linux为目标对项目进行打包。目前&#xff0c;只有Windows支持交叉编译。 交叉编译支持的平台 Windows | Linux-x86_…

有趣的代码——有故事背景的程序设计3

这篇文章再和大家分享一些有“背景”的程序设计&#xff0c;希望能够让大家学到知识的同时&#xff0c;对编程学习更感兴趣&#xff0c;更能在这条路上坚定地走下去。 目录 1.幻方问题 2.用函数打印九九乘法表 3.鸡兔同笼问题 4.字数统计 5.简单选择排序 1.幻方问题 幻方又…

【LeetCode】每日一题 2023_12_2 拼车(模拟/差分)

文章目录 刷题前唠嗑题目&#xff1a;拼车题目描述代码与解题思路学习大佬题解 刷题前唠嗑 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01; 题目&#xff1a;拼车 题目链接&#xff1a;1094. 拼车 题目描述 代码与解题思路 func carPooling(trips [][]int…

智能优化算法应用:基于金鹰算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于金鹰算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于金鹰算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.金鹰算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

7个简单技巧,让你从容应对压力面试!

01-什么是压力面试&#xff1f; 压力面试是指有意制造紧张&#xff0c;以了解求职者将如何面对工作压力的一种面试形式。 事实上&#xff0c;压力面试不是单独存在的一类面试&#xff0c;往往是穿插在面试过程中。 面试人通过提出不礼貌、冒犯的问题&#xff0c;或者用怀疑、…

深入学习Synchronized各种使用方法

文章目录 前言一、synchronized关键字通用在下面四个地方&#xff1a;1.1synchronized修饰实例方法1.2synchronized修饰静态方法&#xff1a;1.3synchronized修饰实例方法的代码块1.4synchronized修饰静态方法的代码块2.读入数据 二.Sychronized关键特性2.1互斥2.2 刷新内存2.3…

Clion自定义管理和配置软件构建过程的工具(代替CMake)构建程序

在公司由于需要x86环境和其他arm环境&#xff0c;同时需要使用公司自定义的mine_x86或者mine_orin对代码进行编译。 编译命令如下mine_x86 build -Dlocal1 -j8,为使用Clion对程序进行调试&#xff0c;需要对程序进行设置。方便调试代码时能够断点查看变量。尝试了很多次&#…

python高级练习题库实验1(B)部分

文章目录 题目1代码实验结果题目2代码实验结果题目3代码实验结果题目4代码实验结果题目5代码实验结果题目总结题目1 打包糖果小游戏,用户输入糖果品牌与个数,还有一个盒子里面可以装多少个糖果,输出一些打印信息,如下图所示: 代码 print("Packaging lollies into…