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/目录

虚目录:显示的是当前进程的文件描述符信息。

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

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

相关文章

12-从URL到页面:探寻Web页面渲染的全过程

从URL到页面&#xff1a;探寻Web页面渲染的全过程 笔记分享 在我们浏览网页时&#xff0c;从输入URL到最终页面呈现在浏览器上&#xff0c;这背后发生了一系列复杂的步骤。本文将详细介绍这个过程&#xff0c;包括TCP连接的建立与终止。 1. DNS解析 当你在浏览器中输入一个U…

工业自动化喷涂生产线设计方案

利用机械臂代替人工进行喷涂工艺生产线的设计实现方案可以减少人工成本&#xff0c;同时提高整厂自动化程度&#xff0c;提高生产效率&#xff0c;改善工人办公环境&#xff0c;本文简单介绍如何利用机械臂代替人工进行自动化喷涂生产线设计。 整体布置包括利用三台埃夫特机械臂…

Github 2024-06-04 Python开源项目日报 Top10

根据Github Trendings的统计,今日(2024-06-04统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目10Shell项目1TypeScript项目1yt-dlp: 一个增强版的youtube-dl分支 创建周期:1184 天开发语言:Python协议类型:The UnlicenseStar数…

数据结构——哈希表、哈希桶

哈希概念 顺序结构以及平衡树中&#xff0c;元素关键码与其存储位置之间没有对应的关系&#xff0c;因此在查找一个元素时&#xff0c;必须要经过关键码的多次比较&#xff0c;顺序查找时间复杂度为O(N),平衡树中为树的高度,即O(logN),搜索的效率取决于搜索过程种元素的比较次…

ElasticSearch学习笔记之一:介绍及EFK部署

1. 系统概述 The Elastic Stack&#xff0c;包括Elasticsearch、Kibana、Beats和Logstash&#xff08;也成为ELK Stack&#xff09; Elasticsearch&#xff1a;简称ES&#xff0c;是一个开源的高扩展的分布式全文搜索引擎&#xff0c;是整个Elastic Stack技术栈的核心。它可以…

docker安装redis以及持久化

为了避免当虚拟机关机后redis数据丢失的情况&#xff0c;redis需要持久化。所以要挂载数据卷 创建数据和配置存放的目录 [root192 data]# pwd /root/data [root192 data]# mkdir -p /root/data/redis/conf && chmod 777 /root/data/redis/conf [root192 data]# mkdir …

Ant Design Vue 动态表头并填充数据

在使用 Ant Design Vue 动态生成表头并填充数据时&#xff0c;你需要以下几个关键步骤&#xff1a; 1. **安装 Ant Design Vue**&#xff1a; 确保你已经安装并配置了 Ant Design Vue。 bash npm install ant-design-vue 2. **引入 Ant Design Vue 组件**&#xff…

怎么找抖音视频素材?下载抖音的素材视频网站分享给你

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

香橙派Orange AI Pro / 华为昇腾310芯片 部署自己训练的yolov8模型进行中国象棋识别

香橙派Orange AI Pro / 华为昇腾310芯片 部署自己训练的yolov8模型进行中国象棋识别 一、香橙派简介1.1、香橙派 AI Pro 硬件资源介绍1.2、华为昇腾310&#xff08;Ascend310&#xff09; 简介1.3、 昇腾310AI能力和CANN 简介昇腾310 NPU简介 二、远程环境配置2.1、ssh2.2、vnc…

深入理解 Python3 函数:从基础语法到高级应用

Python3 函数是构建模块化代码的基本单位&#xff0c;允许我们将代码组织成独立的、可重用的块。本文将详细介绍 Python3 函数的基本语法、常用命令、示例、应用场景、注意事项&#xff0c;并进行总结。 基本语法 在 Python 中&#xff0c;函数的定义使用 def 关键字&#xf…

VScode中Markdown图片尺寸大小调整

自存用&#xff0c;不保证适用于所有人 默认情况 ![图片描述](2024-06-03-11-57-36.png)图片居中且改变尺寸 <div aligncenter><img src"2024-06-02-15-09-50.png" width"400"></div>"2024-06-02-15-09-50.png"是图片链接&…

HTML5 Canvas 绘图教程二

在本教程中&#xff0c;我们将探讨 canvas 的高级用法&#xff0c;包括复杂的绘图 API、坐标系统和变换操作、平滑动画技术以及复杂应用和游戏开发的实践。 1. 绘图 API 高级方法 1.1 二次贝塞尔曲线 (quadraticCurveTo) 二次贝塞尔曲线需要两个点&#xff1a;一个控制点和一…

沈阳 2024年 融资融券怎么开通,利率多少?

融资融券是什么&#xff0c;为什么能赚钱&#xff0c;怎么赚更多&#xff0c;怎么少付利息 100个4.2% 如果你发现了好股票、好机会&#xff0c;但目前券商的融资利率较高&#xff0c;可以考虑转户并选择低利率的券商&#xff0c; 同时需要注意开通条件和转户产生的成本费用。…

新书推荐:1.3 内存管理模式

本节必须掌握的知识点&#xff1a; 4GB虚拟空间 虚拟内存 多任务切换 1.3.1 4GB虚拟空间 ■Win16操作系统 Windows1.0版本为16位操作系统&#xff0c;支持16位处理器实模式&#xff0c;最大寻址空间为1MB。Win16操作系统的内存管理非常简单&#xff0c;采用分段内存管理模式…

I.MX RT1170之MIPI DSI初始化和显示流程详解

MIPI DSI&#xff08;Mobile Industry Processor Interface Display Serial Interface&#xff09;是一种广泛应用于移动设备显示屏的接口标准。由MIPI联盟制定&#xff0c;DSI接口旨在提供高效、低功耗的显示屏数据传输解决方案。 本节来就通过学习I.MX RT1170单片机中的MIPI…

【Linux】Linux项目自动化构建工具——make/Makefile

1.背景 会不会写makefile&#xff0c;从一个侧面说明了一个人是否具备完成大型工程的能力一个工程中的源文件不计数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;makefile定义了一系列的 规则来指定&#xff0c;哪些文件需要先编译&#xff0c;哪些文件需…

Java集合思维导图

详细内容请看链接内容 Java集合面试题集——2024最新大厂面试

用于对话场景的文本转语音-chattts

网址 https://chattts.com/zh 多语言支持 ChatTTS 的一个关键特性是支持多种语言&#xff0c;包括英语和中文。这使其能够为广泛用户群提供服务&#xff0c;并克服语言障碍 大规模数据训练 ChatTTS 使用了大量数据进行训练&#xff0c;大约有1000万小时的中文和英文数据。这…

【图像识别系统】表情识别Python+人工智能深度学习+TensorFlow+卷积算法网络模型+图像识别

表情识别系统&#xff0c;本系统使用Python作为主要编程语言&#xff0c;通过TensorFlow搭建ResNet50卷积神经算法网络模型&#xff0c;通过对7种表情图片数据集&#xff08;‘Neutral’, ‘Anger’, ‘Disgust’, ‘Fear’, ‘Happy’, ‘Sad’, ‘Surprise’&#xff09;进行…

OpenGL系列(三)VBO、VAO

在OpenGL系列&#xff08;一&#xff09;三角形 用到了VBO和VAO&#xff0c;本文对两者进行介绍。 通过OpenGL的API绘制图形时&#xff0c;需要先定义顶点&#xff0c;如示例中三角形的顶点数组定义如下。 float vertices[] {// 位置信息 // 颜色信息0.5f, -0.5f, 0.…