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…...

随机数相关
产生随机数对象 固定写法: Random 随机数变量名 new Random();Random r new Random();生成随机数 int i r.Next(); //生成一个非负数的随机数 Console.WriteLine(i);i r.Next(100); // 生成一个 0~99的随机数 左边始终是0 左包含 右边是100 右不包含 Consol…...

EulerMaker Yocto Open Build Service
EulerMaker & Yocto & Open Build Service 1 介绍1.1 概述 2 工具2.1 Yocto 【嵌入式领域】介绍目标好处三大关键组件创建流程发行版本 2.2 Open Build Service 【OBS】【服务器领域】介绍应用 2.3 EulerMaker 【全场景】介绍特性需求背景(1)能支…...

SQL面试问题集
目录 Q.左连接和右连接的区别 Q.union 和 union all的区别 1、取结果的交集 2、获取结果后的操作 Q.熟悉开窗函数吗?讲一下row_number和dense_rank的区别。 Q.hive行转列怎么操作的 Q.要求手写的题主要考了聚合函数和窗口函数,row_number()&#…...

基于单片机的八路抢答器设计论文
绪 论1.1 课题研究的相关背景 抢答器是一种应用非常广泛的设备,在各种竞赛、抢答场合中,它能迅速、客观地分辨出最先获得发言权的选手。早期的抢答器只由几个三极管、可控硅、发光管等组成,能通过发光管的指示辩认出选手号码。现在大多数抢答器均使用单片机(如MCS-5…...

一个最简单基于spring的websocket服务端+客户端实现案例
1、服务端 代码分为两部分: 一个是服务器终端类:用java注解来监听连接ServerEndpoint、连接成功OnOpen、连接失败OnClose、收到消息等状态OnMessage import org.springframework.stereotype.Component;import javax.websocket.*; import javax.websoc…...

三.二、关于 Vue.js 中`transition`组件使用:页面切换动画和标签移动动画都是要用到的
一、引言 在 Vue.js 中,transition组件提供了一种简单而强大的方式来实现页面过渡效果。它可以让元素在状态改变时,如进入或离开视图时,以平滑的动画方式进行过渡。通过transition,我们可以为应用增添更加生动和吸引人的用户体验…...

指纹考勤系统
目录 1.课题研究目的和内容 1.1 课题研究目的 1.2 课题研究内容 2.系统总体方案设计及功能模块介绍 2.1总体方案设计 2.2 ATK-301模块介绍 2.3 TFTLCD显示功能模块介绍 2.4 蜂鸣器报警功能模块介绍 2.5 时钟模块介绍 3.系统硬件设计与实现 3.1 系统硬件电…...

怎么找抖音视频素材?下载抖音的素材视频网站分享给你
在这个视觉印象至关重要的时代,选用高质量的视频素材对于制作抖音视频来说是关键。如果你正在寻找适合的视频素材来丰富你的抖音创作,以下这份详细的视频素材网站指南将帮助你迈出第一步。 蛙学府网 蛙学府网提供了丰富多样的视频素材,包括动…...

【pytorch】大模型训练张量并行
Large Scale Transformer model training with Tensor Parallel (TP) 张量并行如何工作 原始 Tensor Parallel (TP) 模型并行技术于Megatron-LM论文中被提出,是一种用于培育大规模Transformer模型的高效模型并行技术。我们在本练习指南中介绍的序列并行 (SP) 实际…...

Flutter 中的 CupertinoSliverNavigationBar 小部件:全面指南
Flutter 中的 CupertinoSliverNavigationBar 小部件:全面指南 Flutter 是一个由 Google 开发的跨平台 UI 框架,它允许开发者使用 Dart 语言来构建高性能、美观的移动、Web 和桌面应用。在 Flutter 的丰富组件库中,CupertinoSliverNavigation…...