C语言:IO操作
引言
I/O操作是一切实现的基础。IO即为input &output
标准IO(stdio)
FILE类型贯穿始终,FILE是由typedef定义出来的
vii /usr/include/asm-generic/errno-base.h (errno定义的位置)
/usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h 结构体所在位置(struct _IO_FILE)
fopen
打开一个文件。
errno是之前是一个整形现在一个预定义的宏,可以用gcc -E查看
perror函数:可以打印出错的信息
strerror:将errno的数据转为字符串输出。
FILE *fopen(const char *pathname, const char *mode);
返回:FILE指针,指针存在于堆区。
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main()
{FILE*fp = fopen("temp","r");if(fp==NULL){perror("Error opening file");fprintf(stderr,"fopen() failed:%d %s\n",errno,strerror(errno));exit(1);}puts("OK");return 0;
}
最大的打开文件数量
count = 65533,除了文件操作默认还打开了stdio,stdout,stderr,一共65526,可以使用ulimit -a查看linux设置的系统上线。
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main()
{int count = 0;FILE*fp;while(1){fp = fopen("temp","w");if(fp==NULL){perror("Error opening file");break;}count++;}puts("OK");printf("count = %d \n",count);return 0;
}
文件权限
4是读,2是写,1是可执行。文件权限为8进制数
0666 & ~umask
umask输出0002(是一个8进制数)000 000 010
取反相当于 111 111 101
110 110 110 & 111 111 101 = 110 110 100
fclose
关闭一个文件,成功返回0,失败返回EOF宏
fclose(fp);
fgetc
diff命令:比较两个文件的区别,不输出代表内容一致。
getc是宏,fegtc是函数来使用。宏编译时被替换,占用编译,函数在运行,占用运行时间。返回值为int,读到EOF代表读取到了末尾。
getchar == getc == fgetc
fputc
putchar == putc == fputc
mycopy
#include <stdlib.h>
#include <stdio.h>
#include <error.h>
#include <string.h>int main(int argc,char **argv)
{FILE*fps,*fpd;int ch;if(argc <3){fprintf(stderr,"Usage:%s <src_file> <dest_file>\n",argv[0]);exit(1);}fps = fopen(argv[1],"r");if(fps ==NULL){perror("fopen");exit(1);}fpd = fopen(argv[2],"w");if(fpd ==NULL){fclose(fps);perror("fopen");exit(1);}while(1){ch = fgetc(fps);if(ch == EOF)break;fputc(ch,fpd);}fclose(fpd);fclose(fps);return 0;
}
fgets
编辑器末尾会产生'\n'
stream = "abcd"
fgets(buf,5,stream);
此时需要读取两次才会读取完毕。
fputs
mycopy_fgets
#include <stdlib.h>
#include <stdio.h>
#include <error.h>
#include <string.h>int main(int argc,char **argv)
{FILE*fps,*fpd;int ch;char buf[1024];if(argc <3){fprintf(stderr,"Usage:%s <src_file> <dest_file>\n",argv[0]);exit(1);}fps = fopen(argv[1],"r");if(fps ==NULL){perror("fopen");exit(1);}fpd = fopen(argv[2],"w");if(fpd ==NULL){fclose(fps);perror("fopen");exit(1);}while(1){if(fgets(buf,1024,fps)==NULL)break;fputs(buf,fpd);}fclose(fpd);fclose(fps);return 0;
}
fread
二进制流读取,架设数据量足够。
fread(buf,1,10,fp) -- 数据量不足,可以读取一部分
fread(buf,10,1,fp)--数据量不足,会读取失败。
fwrite
返回写入正常的个数
mycopy_fread
#include <stdlib.h>
#include <stdio.h>
#include <error.h>
#include <string.h>int main(int argc,char **argv)
{FILE*fps,*fpd;int ch;int len;char buf[1024];if(argc <3){fprintf(stderr,"Usage:%s <src_file> <dest_file>\n",argv[0]);exit(1);}fps = fopen(argv[1],"r");if(fps ==NULL){perror("fopen");exit(1);}fpd = fopen(argv[2],"w");if(fpd ==NULL){fclose(fps);perror("fopen");exit(1);}while(1){len = fread(buf,1,1024,fps);if(len ==0 )break;fwrite(buf,1,len,fpd);}fclose(fpd);fclose(fps);return 0;
}
printf
打印语句,同类函数族:
int fprintf(FILE *stream, const char *format, ...);:在文件流输出
int sprintf(char *str, const char *format, ...);,格式化输出
int snprintf(char *str, size_t size, const char *format, ...);指定大小
返回写入的字符个数
scanf
从终端获取数据,同类函数族:
int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);从指定流拿内容,放在。。。地址中
int sscanf(const char *str, const char *format, ...);将长的字符串按照格式,解析到地址
遵循
POSIX.1-2001, POSIX.1-2008, C89, C99.
fseek
操作文件位置指针,定位到指定位置
int fseek(FILE *stream, long offset, int whence);
- stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了流。
- offset -- 这是相对 whence 的偏移量,以字节为单位。
- whence -- 这是表示开始添加偏移 offset 的位置。它一般指定为下列常量之一
-
常量 描述 SEEK_SET 文件的开头 SEEK_CUR 文件指针的当前位置 SEEK_END 文件的末尾
ftell
操作文件位置指针
long ftell(FILE *stream);
返回给定流 stream 的当前文件位置。
rewind
操作文件位置指针
void rewind(FILE *stream);
将文件内部的位置指针重新指向一个流(数据流/文件)的开头
fflush
刷新文件缓冲区
int fgetpos(FILE *stream, fpos_t *pos) 获取流 stream 的当前文件位置,并把它写入到 pos。如果成功,该函数返回零。如果发生错误,则返回非零值
int fsetpos(FILE *stream, const fpos_t *pos) 设置给定流 stream 的文件位置为给定的位置。参数 pos 是由函数 fgetpos 给定的位置。如果成功,该函数返回零值,否则返回非零值,并设置全局变量 errno 为一个正值,该值可通过 perror 来解释。
缓冲区
作用是:合并系统调用。
行缓存:换行的时候进行刷新,满了进行刷新,强制刷新
全缓存:满了刷新,强制刷新(默认,只要不是终端设备)
无缓存:stderr,需要立即输出
setvbuf,改缓冲区
getline
在标准C语言中,getline函数是不存在的。本文介绍的是LINUX下C语言的getline函数(在gcc编译器中,对标准库进行了扩展,加入了一个getline函数。),除此之位C++中还有两个getline函数,一个在stirng中,一个在iostream中。
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
以上函数均无法获取一行内容, getline是一个动态内存申请的函数。
需要定义宏:CFLAGS+= -D_GNU_SOURCE
可以参考文章:C/C++中的getline函数总结_fopen getline-CSDN博客
#include <stdlib.h>
#include <stdio.h>
#include <string.h>int main(int argc,char *argv[])
{if(argc <2){fprintf(stderr,"Usage...\n");return -1;}FILE*fp = fopen(argv[1],"r");if(fp == NULL){perror("fopen");return -1;}char *linebuf=NULL; //必须初始化size_t linesize = 0; //必须初始化while(1){if(getline(&linebuf,&linesize,fp) < 0) //会产生内存泄露,因为是动态申请的malloc 和reallocbreak;printf("%ld-%ld:%p \n",linesize,strlen(linebuf),&linebuf);//linesize为生成的内存大小,第一次为120}// free(getline); 不建议使用fclose(fp);return 0;
}
临时文件
函数
tmpnam
char *tmpnam(char *s);
tmpnam, tmpnam_r - create a name for a temporary file
不是一个安全的操作,需要获取文件指针然后在打开文件,如果并发操作容易产生错误。
缺陷:不是原子操作(产生名字,再创建文件)
tmpfile
FILE *tmpfile(void);
安全的临时文件,产生匿名文件(ls -a看不到)。可以直接打开文件。不会产生冲突,也不用担心销毁的问题fclose会自动释放。
如何不冲突创建临时文件
/tmp目录是临时目录,使用tmpfile可以不冲突
及时销毁
tempfile生成的临时文件当文件关闭后自动删除---匿名文件(没名字:ls命令看不到)
问题
fseek和ftell的第二个参数是long类型,32位下是32字节,可能会溢出,引出:fseeko, ftello,把第二个参数定义为宏off_t。
#define _FILE_OFFSET_BITS 64 可以修改off_t为64位
gcc a.c -D__FILE_OFFSET_BITS=64
但是遵循的协议是 POSIX.1-2001, POSIX.1-2008, SUSv2.
系统调用IO/文件IO(sysio)
标准IO依赖于系统调用IO
文件描述符是在文件IO中贯穿始终的类型。
文件描述符的概念
本质是一个整型数,是数组的下标 ,存放的是结构体,使用数组指针进行封装,返回下标。数组的大小上限为ulimit -a中 open files的大小,使用时优先使用最小的那一个。每一个进程(启动的程序)都会存在这个数组。可以用以下程序进行测试。写的时候不会出现覆盖的情况。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>int main()
{FILE*fp = fopen("./temp","a+");int inode = fileno(fp);printf("inode = %d \n",inode);srand(time(NULL));char buf[16];sprintf(buf,"hello_%d \n",rand()%100 );fwrite(buf,1,strlen(buf),fp);
// fflush(fp);while(1){int q = getchar();if(q == 'q')break;}return 0;
}
文件IO操作
open
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
r- >O_RDONLY
r+ -> O_RDWR
w -> O_WRONLY|O_CREAT|O_TRUNC
w+ -> O_RDWR|O_CREAT|O_TRUNC
mode_t: 8进制数
close
与fclose类似。
read
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
write
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
lseek
同seek
#include <stdlib.h>
#include <stdio.h>
#include <error.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main(int argc,char **argv)
{int fps,fpd;int ret;char buf[128];int len,pos;if(argc <3){fprintf(stderr,"Usage:%s <src_file> <dest_file>\n",argv[0]);exit(1);}fps = open(argv[1],O_RDONLY);if(fps <0){perror("open");exit(1);}fpd = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0600 );if(fpd <0){close(fps);perror("open");exit(1);}while(1){len = read(fps,buf,128);if(len < 0){perror("read()");break;}if(len ==0)break;pos = 0;while(len > 0){ret = write(fpd,buf+pos,len);if(ret <0){perror("write()");exit(1);}pos += ret;len-=ret;}}close(fpd);close(fps);return 0;
}
文件IO与标准IO的区别
举个例子:传达室老大爷跑邮局。
区别:响应速度 & 吞吐量
标准IO 吞吐量大,文件IO响应速度快。
面试:如何是一个程序变快?
从吞吐量和响应速度两方面进行回答
用户体验:比较喜欢吞吐量。
提醒:标准IO和文件IO不可以混用。
函数:int fileno(FILE*fp) 将标准IO转为文件IO
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>int main()
{putchar('a');write(1,"b",1);putchar('a');write(1,"b",1);putchar('a');write(1,"b",1);exit(0);}
输出结果:bbbaaa
因为文件IO比标准io快。
引入命令:strance:帮我门看一个可执行程序的系统调用是如何发生的。
IO的效率问题
time命令:查看程序执行的时间
real 0m0.007s user+sys +一点点调度等待 时间(真实时间)
user 0m0.007s 使用时间
sys 0m0.000s 系统调用消耗时间
栈空间在 1024*8500左右时,运行会出现core的情况。
文件共享
含义:多个任务共同操作一个文件或者协同完成任务。
面试:写程序删除一个文件的第十行。
补充函数:truncate/ftruncate可以把文件截断到指定的长度
原子操作
不可分割的最小单位。不可分割的操作。
原子操作的作用:解决竞争和冲突。
如:tmpnam命令 在申请文件时候还没有创建,使用才创建,同时别人在申请是已经创建了会错误。
程序中的重定向
可以把原有的文件描述符stdout(1)关掉,然后使用open打开文件,此时文件所在表述符为1
dup
复制旧文件描述符,作为新的描述符(为当前最小的描述符)。不是原子操作
int dup(int oldfd);
dup2
dup2是原子操作,把newfd最为old的副本,如果newfd被占用就关闭
int dup2(int oldfd, int newfd);
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>#define FILE_NAME "/tmp/out"int main()
{int fd = open(FILE_NAME,O_WRONLY|O_CREAT|O_TRUNC,0600);printf("fd = %d \n",fd);//下面两步不原子,容易出现被别人打断的情况。
// close(1);
// int d = dup(fd);//dup2是原子操作int d = dup2(fd,1);printf("dup = %d \n",d);if(fd != 1){close(fd);}puts("hello! ");return 0;
}
同步
sync
用于跟设备通信会使用到。关机(解除设备挂载)
sync, syncfs - commit filesystem caches to disk(将文件系统缓存提交到磁盘)
void sync(void)
fsync
指定一个文件进行刷新,将处于核心状态的文件与存储设备同步
int fsync(int fd);
fdatasync
int fdatasync(int fd);
只刷数据不刷亚数据。
数据:文件中有效的内容。
亚数据:文件最后的修改时间、文件的属性。
fcntl
文件描述所变的魔术几乎都来源于该函数。
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
ioctl
设备相关的内容
/dev/fd/目录
虚目录:显示的是当前进程的文件描述符信息。
相关文章:
C语言:IO操作
引言 I/O操作是一切实现的基础。IO即为input &output 标准IO(stdio) FILE类型贯穿始终,FILE是由typedef定义出来的 vii /usr/include/asm-generic/errno-base.h (errno定义的位置) /usr/include/x86_64-linux-gnu/bits/types/struct…...
算法 | 刷题日记
1.递归通常是用栈来实现的 递归在其本质上是通过函数调用栈(Call Stack)来实现的,而不是队列(Queue)。当你调用一个函数时,该函数的局部变量、参数和返回地址会被压入(push)到一个由…...
微信小程序登录接口
微信小程序登录,实现思路分析: 用户触发登录操作:用户在微信小程序中点击“登录”按钮,触发登录流程。调用微信登录接口:小程序端调用微信提供的登录接口(如wx.login),获取临时登录…...
VBA实战(Excel)(5):介绍一种排列组合算法
1. 需求场景 有多个条件,条件个数不定,每个条件有若干种情况,情况个数不定,输出所有条件可能的情况的排列组合。 2.举例 假设第一次有5个情况要填,第一个条件20种情况,第二个5种,第三个40种&…...
迭代器的使用
参考: 生成器迭代器next函数 迭代器的使用 说到迭代器就必须先要提一下可迭代对象(iterable),可迭代对象是能够逐一返回其成员项的对象。可迭代对象包括序列类型(如list、str、tuple)和非序列类型&#…...
安卓手机APP开发___广播概述
安卓手机APP开发___广播概述 目录 概述 关于系统广播 系统广播所发生的更改 接收广播 清单声明的接收器 上下文注册的接收器 对进程状态的影响 发送广播 通过权限限制广播 带权限的发送 带权限的接收 安全注意事项和最佳做法 概述 Android 应用可以通过 Android …...
【封装】Unity切换场景不销毁物体
在切换场景时,如果物体不需要销毁,可以直接使用下方脚本 代码 public class DontDestroyLoader : MonoBehaviour{ //所有不销毁的物体预制体[SerializeField] private GameObject[] dontDestroyPrefabs;//实例化预制体public void Load(){foreach (var …...
基于学习的决策树
基于学习的决策树概述 决策树是一种监督学习方法,广泛应用于分类和回归任务中。基于学习的决策树模型通过学习数据中的特征来构建树状结构,帮助做出决策。以下是对基于学习的决策树的详细介绍,包括其基本概念、工作流程、构建算法、优势和挑…...
godot.bk2
1.$node_name 其实 就是 get_node 的语法糖 2.场景内部用get_node,场景外部用信号 这是自定义信号的绑定,如果是内置信号,直接右键点击链接到一个函数即可 3.场景切换和摄像头一直居中 4.class_name命名一个类,extends继承&…...
STM32 IIC 使用 HAL 库操作eeprom
在STM32上通过I2C接口(注意:在标准STM32库中,I2C接口通常被写为"I2C"而不是"IIC")与EEPROM芯片通信时,你需要遵循I2C通信协议,并使用STM32的HAL库或标准外设库(如果适用&am…...
YOLOv8+PyQt5海洋船只检测(可以重新训练,yolov8模型,从图像、视频和摄像头三种路径识别检测)
1.效果视频:海洋船只检测yoloV8检测(https://mbd.pub/o/bread/mbd-ZpaYk55r)_哔哩哔哩_bilibili资源包含可视化的海洋船只检测系统,可对于高空拍摄到的海洋图片进行轮船检测,基于最新的YOLOv8训练的海洋船只检测模型&a…...
PCL 高阶多项式曲线回归拟合(二维)
文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 高阶多项式曲线回归(Polynomial Regression)是一种线性回归模型的扩展,它允许数据拟合一个非线性的曲线。虽然多项式本身是非线性的,但我们可以通过引入新的变量(例如,原始变量的平方、立方等)来将问题转化为…...
深入理解 Python3 函数:从基础语法到高级应用
Python3 函数是构建模块化代码的基本单位,允许我们将代码组织成独立的、可重用的块。本文将详细介绍 Python3 函数的基本语法、常用命令、示例、应用场景、注意事项,并进行总结。 基本语法 在 Python 中,函数的定义使用 def 关键字…...
03_初识Spring Cloud Gateway
文章目录 一、网关简介1.1 网关提出的背景1.2 网关在微服务中的位置1.3 网关的技术选型1.4 补充 二、Spring Cloud Gateway的简介2.1 核心概念:路由(Route)2.2 核心概念:断言(Predicate)2.3 核心概念&#…...
python数据分析——线性模型
参考资料:活用pandas库 1、简单线性回归 线性回归的目标是描述响应变量(或“因变量”)和预测变量(也称“特征”、“协变量”、“自变量”)之间的直线关系。本例中将讨论tips数据集中的total_bill对tip的影响。 # 导入…...
网络原理——HTTP/HTTPS ---- HTTPS
T04BF 👋专栏: 算法|JAVA|MySQL|C语言 🫵 今天你敲代码了吗 目录 HTTPS加密与解密HTTPS的工作流程使用对称密钥来加密使用非对称密钥 来对 对称密钥进行加密第三方公证总结 HTTPS https本质上就是在http的基础之上 增加了加密层,抛开加密层之后,剩下的部…...
网络协议二
一、套接字Socket 基于 TCP UDP 协议的 Socket 编程,在讲 TCP 和 UDP 协议的时候,我们分客户端和服务端,在写程序的时候,我们也同样这样分。 在网络层,Socket 函数需要指定到底是 IPv4 还是 IPv6,分别对应设…...
内存映射mmap技术详解
一、mmap基础概念 mmap 即 memory map,也就是内存映射。mmap 是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,…...
react 合成事件
React合成事件-CSDN博客 当然,很高兴为你解释React中的合成事件概念,非常适合React初学者理解。 想象一下,你正在组织一场派对,为了让派对顺利进行,你需要管理各种活动,比如游戏、音乐和食物分配。但是&a…...
springboot配置集成RedisTemplate和Redisson,使用分布式锁案例
文章要点 自定义配置属性类集成配置RedisTemplate集成配置分布式锁Redisson使用分布式锁简单实现超卖方案 1. 项目结构 2. 集成RedisTemplate和Redisson 添加依赖 依赖的版本与继承的spring-boot-starter-parent工程相对应,可写可不写 <!--spring data redis…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
