标准IO与文件IO

news2024/12/24 10:20:23

标准IO通过缓冲机制减少系统调用,实现更高的效率

        全缓冲:当流的缓冲区无数据或无空间时才执行实际IO操作

        行缓冲:当在输入和输出中遇到换行符('\n')时,进行IO操作

                当流和一个终端关联时,典型的行缓冲

        无缓冲:数据直接写入文件,流不进行缓冲

标准IO:stdin、stdout、stderr

         其中stdin和stdout默认行缓冲

缓冲区大小是1024个字节

文件的打开和关闭

打开

FILE *fopen(const char *path, const char *mode)

成功时返回流指针;出错时返回NULL

文件打开的模式(非常重要)

“r” 或 “rb”

以只读方式打开文件,文件必须存在。

“r+” 或 ”r+b”

以读写方式打开文件,文件必须存在。

“w” 或 “wb”

以只写方式打开文件,若文件存在则文件长度清为0。若文件不存在则创建。

“w+” 或 “w+b”

以读写方式打开文件,其他同”w”。

“a” 或 “ab”

以只写方式打开文件,若文件不存在则创建;向文件写入的数

据被追加到文件末尾。

“a+” 或 “a+b”

以读写方式打开文件。其他同”a”

打开的程序

     perror 库函数    头文件stdio.h

     strerror 库函数  头文件 errno.h  string.h

   perror和strerror 功能:打印系统的错误描述(注意:是系统错误,不是你自己代码错误)

 关闭

函数原型:int fclose(FILE *stream)

  1. fclose()调用成功返回0,失败返回EOF(-1),并设置errno
  2. 流关闭时自动刷新缓冲中的数据并释放缓冲区,比如:常规文件把缓冲区内容写入磁盘
  3. 当一个程序正常终止时,所有打开的流都会被关闭
  4. fclose()函数的入参stream必须保证为非空,否则出现段错误。

标准IO的字符输入和输出 

按字符输入

 int  fgetc(FILE *stream);

 int  getc(FILE *stream);   //宏

 int  getchar(void);   //只能读取标准输入的内容

成功时返回读取的字符;若到文件末尾或出错时返回EOF(-1),

getchar()等同于fgetc(stdin)

getc和fgetc区别是一个是宏一个是函数

注意事项:

1函数返回值是int类型不是char类型,主要是为了扩展返回值的范围。

2 stdin 也是FILE *的指针,是系统定义好的,指向的是标准输入(键盘输入)

3 打开文件后读取,是从文件开头开始读。读完一个后读写指针会后移。读写注意文件位置!

4 调用getchar会阻塞,等待你的键盘输入

  

 如下图所示,打开文件后读取,是从文件开头开始读。读完一个后读写指针会后移。读写注意文件位置!

若想要两次fgetc读取同样内容,就重新打开文件 

按字符输出

int  fputc(int c, FILE *stream);

int  putc(int c, FILE *stream);

int  putchar(int c);

成功时返回写入的字符;出错时返回EOF

putchar(c)等同于fputc(c, stdout)

注意事项:

1返回和输入参数都是int类型

2遇到这种错误:Bad file descriptor,  很可能是文件打开的模式错误(只读模式去写,只写模式去读)

int  fputc(int c, FILE *stream);

int  putc(int c, FILE *stream);

int  putchar(int c);

成功时返回写入的字符;出错时返回EOF

putchar(c)等同于fputc(c, stdout)

注意事项:

1返回和输入参数都是int类型

2遇到这种错误:Bad file descriptor,  很可能是文件打开的模式错误(只读模式去写,只写模式去读)

 行输入(读取整个行)

char  *gets(char *s);  读取标准输入到缓冲区s

char *fgets(char *s, int size, FILE *stream);

成功时返回s,到文件末尾或出错时返回NULL

遇到’\n’或已输入size-1个字符时返回,总是包含’\0’

注意事项:

1 gets函数已经被淘汰,因为会导致缓冲区溢出

2 fgets 函数第二个参数,输入的数据超出size,size-1个字符会保存到缓冲区,最后添加’\0’,如果输入数据少于size-1 后面会添加换行符。

 

行输出(写整行)

int  puts(const char *s);

int fputs(const char *s,  FILE *stream);

成功时返回非负整数;出错时返回EOF

puts将缓冲区s中的字符串输出到stdout,并追加’\n’

fputs将缓冲区s中的字符串输出到stream,不追加  ‘\n’

二进制读写

文本文件和二进制的区别:

存储的格式不同:文本文件只能存储文本。

计算机内码概念:文本符号在计算机内部的编码(计算机内部只能存储数字0101001....,所以所有符号都要编码)

二进制读写函数格式:

size_t fread(void *ptr, size_t size, size_t n, FILE *fp);//读取fp中内容到ptr中

void *ptr  读取内容放的位置指针

size_t size 读取的块大小

size_t n 读取的个数

  FILE *fp  读取的文件指针

size_t fwrite(const void *ptr, size_t size, size_t n, FILE *fp);//从ptr中写入到fp中

void *ptr  写文件的内容的位置指针

size_t size 写的块大小

size_t n 写的个数

  FILE *fp  要写的文件指针

注意事项:

文件写完后,文件指针指向文件末尾,如果这时候读,读不出来内容。

解决办法:移动指针(后面讲解)到文件头;关闭文件,重新打开

 

 此时发现并不对,读取stu2是错误的,原因就是上面说的要注意指针的变化

流刷新定位

 int fflush(FILE *fp);

成功时返回0;出错时返回EOF

将流缓冲区中的数据写入实际的文件

Linux下只能刷新输出缓冲区,输入缓冲区丢弃

如果输出到屏幕使用fflush(stdout)

下图这个程序1.txt不会有内容,因为都在缓冲区中。此时需要加入fflush

 

流的定位:

long ftell(FILE *stream);//成功时返回流的当前读写位置,出错时返回EOF

long fseek(FILE *stream, long offset,  int whence);//定位一个流,成功返回0,出错EOF

void rewind(FILE *stream);

fseek 参数whence参数:SEEK_SET/SEEK_CUR/SEEK_END

SEEK_SET:从距文件开头 offset 位移量为新的读写位置

SEEK_CUR:以目前的读写位置往后增加 offset 个位移量

SEEK_END:将读写位置指向文件尾后再增加 offset 个位移量

offset参数:偏移量,可正可负

注意事项:

1.文件的打开使用a模式 fseek无效

2.rewind(fp) 相当于 fseek(fp,0,SEEK_SET);

3.这三个函数只适用2G以下的文件

下面程序是抹去ef

格式化输入输出

格式化输出

int fprintf(FILE *stream, const char *fmt, …);

int sprintf(char *s, const char *fmt, …);

成功时返回输出的字符个数;出错时返回EOF

格式化输入

int fscanf(FILE *stream, const char *format, ...);

int sscanf(const char *str, const char *format, ...);

重点掌握sprintf 和sscanf

标准IO练习

标准IO练习

time()用来获取系统时间(秒数)

time_t time(time_t *seconds) 1970.1.1 0:0:0

localtime()将系统时间转换成本地时间

struct tm *localtime(const time_t *timer)

struct tm {

   int tm_sec;         /* 秒,范围从 0 到 59                */

   int tm_min;         /* 分,范围从 0 到 59                */

   int tm_hour;        /* 小时,范围从 0 到 23                */

   int tm_mday;        /* 一月中的第几天,范围从 1 到 31                    */

   int tm_mon;         /* 月份,范围从 0 到 11                */

   int tm_year;        /* 自 1900 起的年数                */

   int tm_wday;         /* 一周中的第几天,范围从 0 到 6                */

   int tm_yday;        /* 一年中的第几天,范围从 0 到 365                    */

   int tm_isdst;       /* 夏令时                        */   

};

注意:

   int tm_mon;        获取的值要加1是正确的月份

   int tm_year;        获取的值加1900是正确的年份

获取文件内的所有行数量:

   while(fgets(buf,32,fp)!=NULL){

          if(buf[strlen(buf)-1] =='\n'){  //注意判断是否一行太长,没有读完

               linecount++;

          }

}

写完文件记得fflush ,写到磁盘里面去。

标准IO磁盘文件的缓冲区一般为4096

注意和标准输出的全缓冲区别,标准输出是1024

获取文件内的所有行数量:

   while(fgets(buf,32,fp)!=NULL){

          if(buf[strlen(buf)-1] =='\n'){  //注意判断是否一行太长,没有读完

               linecount++;

          }

}

文件IO

文件IO的概念:

什么是文件IO,又称系统IO,系统调用

是操作系统提供的API接口函数。

POSIX接口 (了解)

注意:文件IO不提供缓冲机制

文件IO的API

open  close read read

文件描述符概念:

英文:缩写fd(file descriptor)

是0-1023的数字,表示文件。

0, 1, 2 的含义 标准输入,标准输出,错误

open

int open(const char *pathname, int flags);   不创建文件

int open(const char *pathname, int flags, mode_t mode);  创建文件,不能创建设备文件

成功时返回文件描述符;出错时返回EOF

文件IO和标准的模式对应关系:

r                                O_RDONLY

r+                              O_RDWR

w                               O_WRONLY | O_CREAT | O_TRUNC, 0664

w+                             O_RDWR | O_CREAT | O_TRUNC, 0664

a                                O_WRONLY | O_CREAT | O_APPEND, 0664

a+                              O_RDWR | O_CREAT | O_APPEND, 0664

umask概念:

umask 用来设定文件或目录的初始权限

 文件或目录的初始权限 = 文件或目录的最大默认权限 - umask

 close

int close(int fd)

关闭后文件描述符不能代表文件

 

文件IO的读写和定位

 

容易出错点:

求字符串长度使用sizeof,对二进制数据使用strlen

printf 的字符最后没有’\0’

 注意看下图write使用的是sizeof,此处应该用strlen(遇\0结束)

 

修改后打印

 此时上图buf2中无内容,因为此时文件指针在尾部。此时先关闭再打开,当然也可以使用lseek

输出如图所示

文件定位 

 

 

目录操作和文件属性获取

目录读取

打开目录

#include  <dirent.h>

 DIR  *opendir(const char *name);

 DIR *fdopendir(int fd);  使用文件描述符,要配合open函数使用

DIR是用来描述一个打开的目录文件的结构体类型

成功时返回目录流指针;出错时返回NULL

读取目录

#include  <dirent.h>

 struct  dirent *readdir(DIR *dirp);

struct dirent是用来描述目录流中一个目录项的结构体类型

包含成员char  d_name[256]   参考帮助文档

成功时返回目录流dirp中下一个目录项;

出错或到末尾时时返回NULL

关闭目录

closedir函数用来关闭一个目录文件:

 #include  <dirent.h>

 int closedir(DIR *dirp);

成功时返回0;出错时返回EOF

代码:遍历目录读取,其中.和..代表当前目录和上一级目录

文件属性获取

修改文件权限

chmod/fchmod函数用来修改文件的访问权限:

 #include  <sys/stat.h>

 int  chmod(const char *path, mode_t mode);

 int  fchmod(int fd, mode_t mode);

成功时返回0;出错时返回EOF

注意:在vmwarewindows共享的文件夹下,有些权限不能改变。

获取文件属性

#include  <sys/stat.h>

 int  stat(const char *path, struct stat *buf);

 int  lstat(const char *path, struct stat *buf);

 int  fstat(int fd, struct stat *buf);//同stat,不过传的是文件描述符

成功时返回0;出错时返回EOF

如果path是符号链接,stat获取的是目标文件的属性;而lstat获取的是链接文件的属性

 代码:(ls -l实现)

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

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

相关文章

【06】GeoScene海图或者电子航道图数据自动化质检

1 S-58错误管理器验证产品 在你编辑数据时进行快速的质量检查可以使用S-58错误管理器&#xff0c;S-58错误管理器工具允许您使用IHO S-58验证标准来验证海事数据库中的产品。你可以验证整个产品&#xff0c;或验证产品的当前范围。 1.1验证产品 使用S-58错误管理器工具完成以…

服务器解析漏洞是什么?攻击检测及修复

服务器解析漏洞&#xff08;Server-side Include Vulnerability&#xff0c;SSI漏洞&#xff09;是一种安全漏洞&#xff0c;通常出现在支持服务器端包含&#xff08;SSI&#xff09;功能的Web服务器上。SSI是一种在Web页面中嵌入动态内容的技术&#xff0c;允许开发人员将外部…

Java 数据结构篇-实现二叉搜索树的核心方法

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 二叉搜索树的概述 2.0 二叉搜索树的成员变量及其构造方法 3.0 实现二叉树的核心接口 3.1 实现二叉搜索树 - 获取值 get(int key) 3.2 实现二叉搜索树 - 获取最小…

监控k8s controller和scheduler,创建serviceMonitor以及Rules

目录 一、修改kube-controller和kube-schduler的yaml文件 二、创建service、endpoint、serviceMonitor 三、Prometheus验证 四、创建PrometheusRule资源 五、Prometheus验证 直接上干货 一、修改kube-controller和kube-schduler的yaml文件 注意&#xff1a;修改时要一个节…

neo4j安装报错:neo4j.bat : 无法将“neo4j.bat”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。

neo4j安装报错&#xff1a; neo4j.bat : 无法将“neo4j.bat”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写&#xff0c;如果包括路径&#xff0c;请确 保路径正确&#xff0c;然后再试一次。 解决办法&#xff1a; 在环境变量中的&#xff0c;用户…

手把手教你搭建谷歌Gemini

前言 谷歌上周推出了一款名为 Gemini 的多模态大模型&#xff0c;并且现在发布了免费开放的 Gemini API 供开发者使用。根据谷歌提供的定价信息&#xff0c;Gemini 有两种收费方式。免费版本每分钟可以进行 60 次请求&#xff0c;足够满足个人用户的需求。收费版本目前暂不可用…

你了解Redis中的跳跃表吗?

跳跃表的基本内容&#xff1a; 对于一个有序序列&#xff0c;链表相对于数组来说&#xff0c;删除和插入的效率要快很多&#xff0c;只需要改变指针的指向&#xff0c;但是在查找的时候&#xff0c;数组就要更占优势一些&#xff0c;可以随机访问&#xff0c;然而链表需要从头…

连接SSH报错 / 连接容器SSH

连接SSH报错 / 连接容器SSH 前言被控端主控端连接失败 前言 本文介绍如何通过SSH方式远程连接Linux被控端&#xff0c;并介绍如何解决连接失败问题。 此方法同样适用于SSH连接Docker容器。 被控端 被控端一般为Linux&#xff0c;默认已安装ssh&#xff0c;但需要手动安装ope…

C++ OJ题测试—排序算法效率

目录 OJ链接 一、直接插入排序 二、希尔排序 三、直接选择排序 常规&#xff1a; 第二种&#xff1a; 四、 堆排序 五、冒泡排序 六、快速排序 常规&#xff1a; 三路划分优化效率 七、归并排序 八、计数排序 OJ链接 ​ 一、直接插入排序 class Solution { pub…

Gateway No servers available for service

springCloud集成网关测试报错找不到服务&#xff0c;如下 造成这种错误可能是下面两种原因 1、nacos注册的服务不在一个命名空间内&#xff0c;导致找不到服务503 spring cloud:nacos:discovery:server-addr: 127.0.0.1:8848config:server-addr: 127.0.0.1:8848file-extensio…

探索Qt 6.3:了解基本知识点和新特性

学习目标&#xff1a; 理解Qt6.3的基本概念和框架&#xff1a;解释Qt是什么&#xff0c;它的核心思想和设计原则。学会安装和配置Qt6.3开发环境&#xff1a;提供详细的步骤&#xff0c;让读者能够顺利安装和配置Qt6.3的开发环境。掌握Qt6.3的基本编程技巧&#xff1a;介绍Qt6.…

欧洲版OpenAI疑似将在24年发布并开源GPT-4级别模型!

大家好&#xff0c;我是二狗。 今天在推特上看到一条振奋人心的消息&#xff1a; “ 欧洲版OpenAI、法国初创公司 Mistral 首席执行官 Arthur Mensch 在法国国家广播电台宣布&#xff0c;Mistral 将在 2024 年发布开源 GPT-4 级别模型。” 这位老哥接着表示甚至可能是免费的&a…

C++ STL——栈和队列(stack queue)

本节目标 1.stack的介绍和使用及其模拟实现 2.queue的介绍和使用及其模拟实现 3.priority_queue的介绍和使用及其模拟实现 4.容器适配器 1.stack的介绍和使用及其模拟实现 1.1 stack的介绍 stack的文档介绍 根据stack的文档介绍可以知道&#xff0c;stack是一种容器适配器…

原生微信小程序-使用 阿里字体图标 详解

步骤一 1、打开阿里巴巴矢量图标库 网址&#xff1a;iconfont-阿里巴巴矢量图标库 2、搜索字体图标&#xff0c;鼠标悬浮点击添加入库 3、按如下步骤添加到自己的项目 步骤二 进入微信开发者工具 1、创建 fonts文件夹 > iconfont.wxss 文件&#xff0c;将刚才的代码复制…

结果实例: 一个cpu的parsec结果

简介 限于篇幅限制&#xff0c;很多教程和论文只展示部分结果。我们这里展示非常细节的结果&#xff0c;包括输出的许多命令行结果。 运行命令行 的shell窗口 ./build/X86/gem5.opt -d m5out/onlyoneCPUkvmCheckPointDifferRCS20231218restore \configs/deprecated/example/…

杰发科技AC7840——SPM电源管理之低功耗模式

0、SPM简介 很早以前就听过低功耗模式&#xff0c;一直没有怎么深入了解&#xff0c;最近遇到几个项目都是跟低功耗有关。正好AutoChips的芯片都有电源管理的功能&#xff0c;在此借用AC7840的SPM对低功耗进行测试。 1、AC7840的5种功耗模式 2、AC7840的模式转换 3、唤醒 在…

Kubernetes 的用法和解析 -- 5

一.企业级镜像仓库Harbo 准备&#xff1a;另起一台新服务器&#xff0c;并配置docker yum源&#xff0c;安装docker 和 docker-compose 1.1 上传harbor安装包并安装 [rootharbor ~]# tar xf harbor-offline-installer-v2.5.3.tgz [rootharbor ~]# cp harbor.yml.tmpl harbor…

Home Assistant 如何开启SSH服务

环境&#xff1a; Home Assistant 11.2 SSH & Web Terminal 17.0 问题描述&#xff1a; Home Assistant 如何开启SSH服务 解决方案&#xff1a; 通过添加一个名为Terminal & SSH的插件来在 Home Assistant 中启用 SSH 服务 下面是启用 SSH 服务的大致步骤&#x…

C语言数据结构-排序

文章目录 1 排序的概念及运用1.1 排序的概念1.2 排序的应用 2 插入排序2.1 直接插入排序2.2 希尔排序2.3 直接排序和希尔排序对比 3 选择排序3.1 堆排序3.2 直接选择排序 4 交换排序4.1 冒泡排序4.2 快速排序4.2.1 挖坑法14.2.2 挖坑法24.2.3 挖坑法3 5 并归排序6 十万级别数据…

Ubuntu中基础命令使用

前言 以下指令测试来自于Ubuntu18.04 如果有说的不对的&#xff0c;欢迎指正与补充 以下指令为我学习嵌入式开发中使用过最多的指令 目录 前言 1 ls 首先我们进入到Linux操作系统中 2 touch创建一个文件 3 pwd查看当前路径 4 创建目录 5 删除文件 6 cd 目录跳转 0…