Linux——stdio

一、基本概念

文件:
    一组相关数据的集合 
文件名:
    01.sh //文件名 

流:

         流是指数据在程序或系统中的流动方式。在Linux中,数据流通常通过文件描述符(File Descriptors)进行管理。文件描述符是一个非负整数,用于标识打开的文件或输入/输出资源。

二、linux下的文件类型 


  b block         块设备文件   eg: 硬盘 
  c character     字符设备文件 eg: 鼠标,键盘
  d directory     目录文件     eg: 文件夹 
  - regular       常规文件     eg: 1.txt 01.sh xx.bmp 
  l symblink      软链接       eg: 快捷方式
  s socket        套接字       eg: 网络通信用
  p pipe          管道         eg: 进程间通信 
 

三、思想

  linux中一个核心设计思想 
  everything is file!
    //一切皆文件 

四、 linux操作文件的函数

   两套函数 (两套操作路径


   
   (一)库函数  

               --- 第三方提供的函数   

 集成了很多功能函数 
    //标准输入输出 
    //数学函数 


   (二)系统调用

               --- 内核提供的函数  

(三)标准io的概念 

1975 Dennis r IO库,
    从C语言的标准,ANSI c 
    IO  input  output
    I: 键盘是标准输入设备 ====》默认输入就是指键盘  /dev/input
    O: 显示器是标准输出设备 ==》默认输出就是指显示器
    
    Linux操作系统当中IO都是对文件的操作
    C一部分,任何支持标准C的系统都可使用标准IO实现文件存储
    标准IO在UNIX上是对文件IO的封装
   
    一般都是对普通文件操作是一种有缓存的IO 在文件IO和用户程序之间,
    加入缓冲区,可以有效减少系统调用的次数,节省系统IO调度资源
    
    说明:
    标准IO库,不单单是linux上有,在windows,Mac os上都有。
    很多操作系统都实现了标准IO库。
    都是依据IOS C标准实现的。
    所以基本保证了可移植性。
    但是因为标准和具体实现之间的差异,
    未必敢保证所有的函数在都可以相互通用。
    
    标准IO都干了些啥?
    标准IO处理了很多细节:
    (1).处理缓冲区分配   (缓存--提高效率 --- 慢速 快速)
    (2).读写IO的块长度的优化
    (3).对系统调用进行了封装,内部对应的"文件描述符" 
    
    好处:
        用户使用方便,不必再担心如何选择正确的块长度。
    //地位:
        标准I/O库是由 Dennis Ritchie在1975年左右编写的。
        它是Mike Lesk编写的可移植I/O库的主要修改版本。
        令人惊讶的是,50年来,几乎没有对标准I/O库进行修改。

五、函数接口

(一)fopen

FILE * fopen(const char *pathname,const char *mode);
  功能:
         流打开函数
  参数:
     @pathname --- 要打开的文件名 //字符串形式的名字 
     @mode     --- 打开的模式 
       r   --- 只读  
       r+  --- 读写 
               说明: 带r的 要求,文件必须存在 ,如果不存在,就会报错
       w   --- 只写 
       w+  --- 读写 
               说明:  
                   文件存在 ,截断成 0长度 
                   不存在,则创建
       a  --- 追加(写)
       a+ --- 读写 
              说明:
                 读 从头读 
                 写 从末尾开始写 
                 文件存在 则打开做写操作即可 
                 文件不存在 创建文件 
  返回值:
     成功 FILE*指针  //文件指针 流指针 --- 从程序上讲,FILE *指针就代表打开的这个文件
     失败 NULL 同时 errno会被设置 
 

#include<stdio.h>
#include<errno.h>

int main(int argc, const char *argv[])
{
	if (argc != 2)
	{
        printf("Usage: %s <filename>\n",argv[0]);
		return -1;
	}

	FILE *fp = fopen(argv[1],"w+");
//	FILE *fp = fopen(argv[1],"r+");

	if(fp == NULL)
	{
		printf("fopen fail\n");
		return -1;
	}

//	printf ("fopen success!\n");
	
	return 0;
}

(二)perror

void perror(const char *s);

#include<stdio.h>
#include<errno.h>

int main(int argc, const char *argv[])
{
	if (argc != 2)
	{
        printf("Usage: %s <filename>\n",argv[0]);
		return -1;
	}

	FILE *fp = fopen(argv[1],"r");

	if(fp == NULL)
	{
		perror("fopen fail");
		return -1;
	}

	printf ("fopen success!\n");
	
	return 0;
}

(三)fgetc  、fputc

1、 int fgetc(FILE * stream);

 功能:
     从文件中读取字符 
 参数:
     @stream 表示要读取的文件对应的流指针 
 返回值:
     成功 对应字符的ASCII码值 
     失败 EOF 到达文件结尾 
          出错 

 2、int fputc(int c,FILE *stream);


  功能:
      将一个字符输出到指定的流(文件)
  参数:
    @c          //要输出的字符 ---ascii码值
    @stream     //指定的文件 
  返回值:  
    成功 被写入的字符的ASCII码值
    失败 EOF 

 

 问题:
   EOF  
   文件中有没有 EOF?  //只是到达结尾时的一个标志

#include<stdio.h>
#include<errno.h>

//类似cat功能

int main(int argc, const char *argv[])
{
	//处理命令行参数
	if (argc != 2)
	{
        printf("Usage: %s <filename>\n",argv[0]);
		return -1;
	}

	//1.打开文件
	FILE *fp = fopen(argv[1],"r+");

	if(fp == NULL)
	{
		perror("fopen fail");
		return -1;
}
	//2.读写数据

	int ret;
	while((ret = fgetc(fp)) != EOF)
	{
		fputc(ret,stdout);
		//printf("%c",ret);
	}

	//3.关闭
	fclose(fp);
	return 0;
}

    
系统默认打开的流指针:
stdin  //标准输入 
stdout //标准输出 
stderr //标准出错 --- 屏幕  --- 可以专门把错误信息输出到 stderr 

#include<stdio.h>

int main(int argc, const char *argv[])
{
	int ret;

	while ( (ret = fgetc(stdin)) != EOF)
		fputc(ret,stdout);
	
	return 0;
}

(四)fclose

int fclose(FILE *stream);
  功能:
     关闭文件 
      刷新流
      关闭了底层文件描述符
 返回值:
   成功 0
   失败 EOF
   注意,不要多次重复关闭

(五)fgets、fputs

1、char * fgets(char*s,int size,FILE*stream)

功能:
   从stream中读取size-1个字符,到s指向的空间 
参数:
  @s        //存放读取到的数据 对应的内存空间 
  @size     //指定一次最多读取多少个字符 
  @stream   //表示要读取的文件 
返回值:
   成功 返回s
   失败 NULL 
        读到文件结尾 也 返回NULL 

注意:
   fgets读取结束:
   1. EOF
   2. '\n'
   3. size-1

 练习:
     统计文件行数 

#include<stdio.h>
#include<errno.h>
#include<string.h>

int main(int argc, const char *argv[])
{
	if(argc != 2)
	{
		printf("Usage: %s <filename>\n",argv[0]);
		return -1;
	}

	FILE *fp = fopen(argv[1],"r+");
	
	if(fp == NULL)
	{
		perror("fopen fail");
		return -1;
	}

	char buf[1024];

	int n = 0;

	while (fgets(buf,sizeof(buf),fp))
	{
		if(buf[strlen(buf) - 1] == '\n')
		{
			n++;
		}
	}

	printf("%d\n",n);

	fclose(fp);
	return 0;
}

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

 功能:
      输出s到stream中
   参数:
    @s 代表要输出的字符串 
    @stream 代表 输出到的文件 
   返回值:
    成功 非负数 
    失败 EOF

 注意:
     不会将 '\0' 输出 

练习:
      cat //fgets实现cat 

#include<stdio.h>
#include<errno.h>

//类似cat功能

int main(int argc, const char *argv[])
{
	//处理命令行参数
	if (argc != 2)
	{
        printf("Usage: %s <filename>\n",argv[0]);
		return -1;
	}

	//1.打开文件
	FILE *fp = fopen(argv[1],"r+");

	if(fp == NULL)
	{
		perror("fopen fail");
		return -1;
}
	//2.读写数据

	int ret;
	while((ret = fgetc(fp)) != EOF)
	{
		fputc(ret,stdout);
		//printf("%c",ret);
	}

	//3.关闭
	fclose(fp);
	return 0;
}

cp_fputsfgets.c 

#include<stdio.h>
#include<errno.h>

int main(int argc, const char *argv[])
{
	if (argc != 3)
	{
        printf("Usage: %s <filename>\n",argv[0]);
		return -1;
	}

	FILE *fp = fopen(argv[1],"r");
	FILE *srt = fopen(argv[2],"w");
    

	if(fp == NULL || srt == NULL)
	{
		printf("fopen fail\n");
		return -1;
	}

	char buf[1024];


	while(fgets(buf,1024,fp) != NULL)
	{
		fputs(buf,srt);
	}

	fclose(fp);
	fclose(srt);


	return 0;
}

"123" --- 文本文件 --- '1''2''3'  //每个数据是按照固定的编码格式存放的 -ASCII
 123   --- 二进制   --- 01111011   //
 
 linux下操作时 ,没有区别 
 windows下区别 
 
 说明:
    1.fgets 和 fputs 在拷贝 二进制文件时 可能出问题 

(六)fread / fwrite

fread/fwrite //二进制读写函数 按对象读写

1、size_t  fread(      void *ptr, size_t size, size_t nmemb, FILE *stream);

2、size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

功能:
     二进制流的读/写
参数:
   @ptr   表示存放数据的空间的地址 
   @size  要操作的单个元素(对象)的大小
   @nmemb 要操作的元素(对象)的个数 
   @stream 要操作的文件 
返回值:
   成功 返回的是 成功操作到的对象的个数 
   失败 0
     到达文件结尾 返回 0
     
应用:
   主要 应用在 文件中 有固定格式的  场景 
 

#include<stdio.h>

int main(int argc, const char *argv[])
{
	char buf[10];
	int ret = fread(buf,sizeof(char),10,stdin);

	printf("ret = %d\n",ret);

	fwrite(buf,sizeof(char),ret,stdout);

	putchar('\n');
	return 0;
}

练习:
   将3个学生的信息,写到文件中 
   之后,
   从文件中读出学生信息,打印

#include<stdio.h>
typedef struct stu
{
	char name[20];
	int sno;
	float score;
}stu_t;

int main(int argc, const char *argv[])
{
	stu_t s[3] = {{"tom",110,99},
		{"liam",111,98},
		{"beta",112,99}};

	FILE *fp = fopen("stu.txt","w+");
	if(fp == NULL)
	{
		perror("fopen fail");
		return -1;
	}

	fwrite(s,sizeof(stu_t),3,fp);

	rewind(fp);

	stu_t s1[3];

	fread(s1,sizeof(stu_t),3,fp);

	int i = 0;
	for(i = 0;i < 3;i++)
	{
		printf("name = %s\n",s1[i].name);
		printf("sno = %d\n",s1[i].sno);
		printf("score = %.2f\n",s1[i].score);
	}
	
	fclose(fp);
	return 0;
}

cat_fread_fwrite.c

#include<stdio.h>

int main(int argc, const char *argv[])
{
	if(argc != 2)
	{
		printf("Usag: %s <filename>\n",argv[0]);
	}

	FILE *fp = fopen(argv[1],"r");

	if(fp == NULL)
	{
		perror("fopen fail");
		return -1;
	}

	char buf[1024];
	int ret = 0;
	while(ret =fread(buf,sizeof(char),1024,fp))
		fwrite(buf,sizeof(char),ret,stdout);

	fclose(fp);

	putchar('\n');


	return 0;
}

(七)文件偏移量  rewind

int  fseek(FILE* stream,long offset,int whence);
   功能:
       定位文件 
   参数:
      @stream  表示要操作文件 
      @offset  表示文件偏移量 
      @whence  定位的参考点 
               SEEK_SET //相对于文件开头的 
                  offset >=0 
               SEEK_CUR //相对于当前位置
                  offset>=0
                  offset<0   //不能超过这个文件开头
               SEEK_END //相对于文件末尾 
                  offset < 0  //不能超过这个文件开头
                  offset >= 0 //可以  --- 创建 空洞 文件
   返回值:
      成功 0
      失败 -1
 

fseek(fp,100,SEEK_SET);//
	 fseek(fp,0,SEEK_SET);//定位到开头 
	 fseek(fp,0,SEEK_END);//定位到末尾

应用:

 创建空洞文件: 
     1.做偏移 
     2.写操作

#include<stdio.h>

int main(int argc, const char *argv[])
{
	if(argc != 2)
	{
		printf("Usage: %s <filename>\n",argv[0]);
		return -1;
	}

	FILE *fp = fopen(argv[1],"r");

	if(fp == NULL)
	{
		perror("file fail");
		return -1;
	}



	if(fseek(fp,100,SEEK_END) != 0)
	{
		perror("fseek fail");
		return -1;
	}

	fputc('A',fp);

	fclose(fp);
	return 0;
}

(八)   long ftell(FILE*stream);

功能:
       获得当前文件的偏移量 
   void rewind(FILE*stream);
   功能:
       将文件偏移量设置到文件开头 


         获得某个文件的大小:
  1. fseek(fp,0,SEEK_END);//定位到末尾
  2. long len =ftell(fp); 

              实现 cp功能

#include<stdio.h>

int main(int argc, const char *argv[])
{
	if(argc != 3)
	{
		printf("Usage: %s <src> <dest>\n",argv[0]);
		return -1;
	}

	FILE *fp1 = fopen(argv[1],"r");

	if(fp1 == NULL)
	{
		perror("file fail");
		return -1;
	}

	fseek(fp1,0,SEEK_END);
	long len = ftell(fp1);

	FILE *fp2 = fopen(argv[2],"w");
	if(fp2 ==NULL)
	{
		perror("file fail");
		return -1;
	}

	fseek(fp2,len-1,SEEK_SET);
	fputc('\0',fp2);

	rewind(fp1);
	rewind(fp2);

	char buf[len];
	fread(buf,sizeof(buf),1,fp1);
	fwrite(buf,sizeof(buf),1,fp2);

	fclose(fp1);
	fclose(fp2);
	return 0;
}

六、缓存

缓存 设计的目的提高效率  
本质上来说 ---缓存其实就是一块内存空间

行缓冲,1k, terminal,主要用于人机交互stdout
    
    缓存区满或者遇到\n刷新    1024
                行缓存多是关于终端的一些操作
                1.遇到\n刷新
                2.缓存区满刷新
                3.程序结束刷新
                4.fflush刷新  fflush(stdout);
                
全缓冲,4k,主要用于文件的读写
    缓存区满刷新缓存区 4096
            对普通文件进行标准IO操作,建立
            的缓存一般为全缓存
            刷新条件:
                1.缓存区满刷新
                2.程序结束刷新
                3.fflush来刷新  fflush(fp);
无缓冲,0k  主要用于出错处理信息的输出 stderr 
    不对数据缓存直接刷新
    printf();==>>stdout 
    fprintf(strerr,"fopen error %s",filename);
                界面交互    出错处理

./a.out < main.c   //< 表示输入重定向 
./a.out > main.c   //> 表示输出重定向 


 


 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

解决 paddle ocr 遇到 CXXABI_1.3.13 not found 的问题

ImportError: /lib/x86_64-linux-gnu/libstdc.so.6: version CXXABI_1.3.13 not found (required by /home/hum/anaconda3/envs/ipc/lib/python3.11/site-packages/paddle/base/libpaddle.so) 通过命令检查 strings /lib/x86_64-linux-gnu/libstdc.so.6|grep CXXABI 而实际上我…

【物联网】电子电路基础知识

文章目录 一、基本元器件1. 电阻2. 电容3. 电感4. 二极管(1)符号(2)特性(3)实例分析5. 三极管(1)符号(2)开关特性(3)实例6. MOS管(产效应管)(1)符号(2)MOS管极性判定(3)MOS管作为开关(4)MOS管vs三极管7. 门电路(1)与门(2)或门(3)非门二、常用元器件…

LLM论文笔记 5: CodeT: Code Generation with Generated Tests

Arxiv日期&#xff1a;2022.7.21机构&#xff1a;Microsoft 关键词 代码补全测试自生成&#xff08;提出&#xff09;Inference 核心结论 1. 更多的测试用例通常可以提高代码大模型的性能&#xff0c;但当测试用例数量达到一定阈值后&#xff0c;性能提升效果减弱 2. 只考虑…

Nginx--日志(介绍、配置、日志轮转)

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 一、Nginx日志介绍 nginx 有一个非常灵活的日志记录模式&#xff0c;每个级别的配置可以有各自独立的访问日志, 所需日志模块 ngx_http_log_module 的…

网络营销新宠:http代理ip为广告投放精准定位保驾护航

在当今数字化时代&#xff0c;网络营销已成为企业推广产品和服务、提升品牌影响力的重要手段。而在众多的网络营销工具中&#xff0c;http代理ip正逐渐崭露头角&#xff0c;成为广告投放精准定位的得力伙伴&#xff0c;为广告投放保驾护航。 http代理ip在广告投放中发挥着多方面…

Python Pandas(7):Pandas 数据清洗

数据清洗是对一些没有用的数据进行处理的过程。很多数据集存在数据缺失、数据格式错误、错误数据或重复数据的情况&#xff0c;如果要使数据分析更加准确&#xff0c;就需要对这些没有用的数据进行处理。数据清洗与预处理的常见步骤&#xff1a; 缺失值处理&#xff1a;识别并…

CodeGPT + IDEA + DeepSeek,在IDEA中引入DeepSeek实现AI智能开发

CodeGPT IDEA DeepSeek&#xff0c;在IDEA中引入DeepSeek 版本说明 建议和我使用相同版本&#xff0c;实测2022版IDEA无法获取到CodeGPT最新版插件。&#xff08;在IDEA自带插件市场中搜不到&#xff0c;可以去官网搜索最新版本&#xff09; ToolsVersionIntelliJ IDEA202…

数字电路-基础逻辑门实验

基础逻辑门是数字电路设计的核心元件&#xff0c;它们执行的是基本的逻辑运算。通过这些基本运算&#xff0c;可以构建出更为复杂的逻辑功能。常见的基础逻辑门包括与门&#xff08;AND&#xff09;、或门&#xff08;OR&#xff09;、非门&#xff08;NOT&#xff09;、异或门…

常见的IP地址分配方式有几种:深入剖析与适用场景‌

在数字互联的世界里&#xff0c;IP地址如同网络世界的“门牌号”&#xff0c;是设备间通信的基础。随着网络技术的飞速发展&#xff0c;IP地址的分配方式也日趋多样化&#xff0c;以适应不同规模、不同需求的网络环境。本文将深入探讨当前主流的几种IP地址分配方式&#xff0c;…

【C语言】C语言 停车场管理系统的设计与实现(源码)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;专__注&#x1f448;&#xff1a;专注主流机器人、人工智能等相关领域的开发、测试技术。 系列文章目录 目录 系列文章目录一、设计要求二、设…

【现代深度学习技术】深度学习计算 | GPU

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈PyTorch深度学习 ⌋ ⌋ ⌋ 深度学习 (DL, Deep Learning) 特指基于深层神经网络模型和方法的机器学习。它是在统计机器学习、人工神经网络等算法模型基础上&#xff0c;结合当代大数据和大算力的发展而发展出来的。深度学习最重…

蓝桥杯备考:贪心算法之纪念品分组

P1094 [NOIP 2007 普及组] 纪念品分组 - 洛谷 这道题我们的贪心策略就是每次找出最大的和最小的&#xff0c;如果他们加起来不超过我们给的值&#xff0c;就分成一组&#xff0c;如果超过了&#xff0c;就把大的单独成一组&#xff0c;小的待定 #include <iostream> #i…

【Elasticsearch】Mapping概述

以下是Elasticsearch中提到的关于Mapping的各模块概述&#xff1a; --- 1.Dynamic mapping&#xff08;动态映射&#xff09; 动态映射是指Elasticsearch在索引文档时&#xff0c;自动检测字段类型并创建字段映射的过程。当你首次索引一个文档时&#xff0c;Elasticsearch会根…

java商城解决方案

数字化时代&#xff0c;电子商务已成为企业拓展市场的重要渠道。对于想要建立在线商店的企业来说&#xff0c;选择正确的技术堆栈至关重要。 Java作为一种成熟且广泛使用的编程语言&#xff0c;为构建购物中心提供了强大的功能和灵活性。 商城Java源码&#xff1a;商城开发的核…

SSM开发(十二) mybatis的动态SQL

目录 一、为什么需要动态SQL? Mybatis 动态 sql 是做什么的? 二、多种动态 SQL 元素 三、示例 1、model定义 2、数据库定义 3、UserMapper接口及UserMapper.xml内容定义 if标签 choose/when/otherwise 标签 foreach标签 trim 标签 四、动态SQL注意 一、为什么需…

HCIA项目实践---OSPF的知识和原理总结

9.5 OSPF 9.5.1 从哪些角度评判一个动态路由协议的好坏&#xff1f; &#xff08;1&#xff09;选路佳&#xff08;是否会出环&#xff09; OSPF 协议采用链路状态算法&#xff0c;通过收集网络拓扑信息来计算最短路径&#xff0c;从根本上避免了路由环路的产生。 &#xff08…

HCIA项目实践---OSPF的基本配置

9.5.12 OSPF的基本配置 &#xff08;所搭环境如上图所示&#xff09; A 先配置IP地址 (先进入路由器R1的0/0/0接口配置IP地址&#xff0c;再进入环回接口配置IP地址) &#xff08;配置R2路由器的0/0/0和0/0/1以及环回接口的IP地址&#xff09; &#xff08;置R3路由器的0/0/0接…

github上创建person access token

在 GitHub 上创建 Personal Access Token&#xff08;PAT&#xff09; 时&#xff0c;权限设置非常重要。正确的权限设置可以确保 Token 能够访问所需的资源&#xff0c;同时避免授予过多权限带来的安全风险。以下是详细的权限设置说明&#xff1a; 1. 进入 Token 创建页面 登录…

【网络编程】之Udp网络通信步骤

【网络编程】之Udp网络通信步骤 TCP网络通信TCP网络通信的步骤对于服务器端对于客户端 TCP实现echo功能代码实现服务器端getsockname函数介绍 客户端效果展示 对比两组函数 TCP网络通信 TCP网络通信的步骤 对于服务器端 创建监听套接字。&#xff08;调用socket函数&#xff…

【教程】MySQL数据库学习笔记(七)——多表操作(持续更新)

写在前面&#xff1a; 如果文章对你有帮助&#xff0c;记得点赞关注加收藏一波&#xff0c;利于以后需要的时候复习&#xff0c;多谢支持&#xff01; 【MySQL数据库学习】系列文章 第一章 《认识与环境搭建》 第二章 《数据类型》 第三章 《数据定义语言DDL》 第四章 《数据操…