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…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...

使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...