Linux - IO(标准IO)

  1. 基础知识:

内核:负责管理一部分硬件资源
系统调用:内核提供给用户访问其内部操作的一些函数接口

IO的分类

标准IO
POSIX标准:可移植操作系统接口规范
POSIX 标准 : 规定 函数功能, 返回值,函数的参
文件IO(系统调用)
main.c

   main()


   {

          fread();

          fwrite();

   }
   -------------------------------------------------------
   标准IO         printf             scanf()//不同的系统有不同的输入输出函数,导致程序可移植性差,为此标准I/O应运而生(采取POSIX标准)

标准IO的
本质: 是对系统调用的再次封装
作用:
增强了代码的可移植性,复用性
提高了效率。
标准IO增加了一个【相当重要:缓冲机制】

系统调用:(文件IO)
不带缓冲区
操作系统直接提供的函数接口
调用 系统调用 是很耗费资源的

 ``  **建议: 使用标准IO读写文件**``

两类函数
标准IO:标准C库里提供的
只要开发环境中安装了标准C库就可以使用 - 可移植 性好
设有缓冲区,每次对文件操作的时候先操作缓冲区,必要时再通过
系统调用访问真实的文件

文件IO:操作系统提供
需要操作系统兼容和POSIX标准
每次对文件操作时都需要通过系统调用访问真实的 文件 - 系统开销比较大

缓冲区
是系统预留的一部分特定的内存,用来缓存输入和输出的数据
缓冲区的类型
全缓冲
当填满缓冲区,再进行实际的IO操作
用标准IO打开文件时
行缓冲
当遇到换行符,再进行实际的IO操作
scanf, printf
无缓冲
直接进行实际的IO操作
perror

  1. 标准IO - 设有缓冲区
    操作对象:流 - FILE
    文件一般操作步骤: 打开文件 - 读写操作 - 关闭文件
    man 3 C库里的函数
    这里函数太多 及不知就man 这是真理 使用多了之后自然就记住了
    标准IO系统过有三种预定义的流在stdio.h中预定的
    标准输入流 stdin
    标准输出流 stdout
    标准出错流 stderr
    1)打开文件
    FILE *fopen(const char *path, const char *mode);
    参数1:打开的文件的路径
    参数2:打开文件的方式
    r :只读,要求文件要存在
    r+:可读可写,要求文件要存在
    w :只写,不存在创建,存在会清空
    w+:可读可写,不存在创建,存在会清空
    a :追加的方式打开(只写),不存在创建,存在在末尾追加
    a+:追加的方式打开(可读可写),不存在创建,存在在末尾追加
    返回值:成功 - 流指针
    失败 - NULL,设置错误码
    1)文件的读操作
    【1】按照字符读取
    功能:从指定流中读取一个字符
    int fgetc(FILE *stream);
    int getc(FILE *stream);
    参数:流指针
    返回值:成功 - 读取到的字符
    失败或者读到文件尾 - EOF
    int getchar(void); === fgetc(stdin);

练习:使用fgetc实现读取文件中所用内容

#include <stdio.h>
int main( int argc, char*argc[])
{
	int ret;
	FILE *fp = NULL;
	fopen(argv[1],"r")//从终端中获取要用只读方式打开的文件
	if(fp == NULL)
	{
		perror("open file failed\n")//打开文件失败打印失败信息
		return -1;//结束程序的执行
	}
	while(1)//不断地在文件中一个字符一个字符的读取数据
	{
		ret = fget(fp);
		if(ret == EOF)break;//读取结束跳出循环
   	printf("%c",ret);//不断地将读取到数据打印在终端
	}
	return 0;
}

【2】按行读取
char *fgets(char *s, int size, FILE *stream);
参数1:用来保存读取到内容
参数2:读取的大小 - 字节 ,一行有n的字符
size <= n - size-1个字节
size > n - n个字节
参数3:流指针
返回值:成功 - s
失败/读到文件尾 - NULL

char *gets(char *s); == fgets(s, size, stdin);
注意:gets函数 换行符不作为有效字符读取

练习:fgets统计文件中有多少行

#include <stdio.h>
#include <string.h>
int main(int argc,char *argv[])
{
	int len =0;
	char buf[10] = {0};
	char *p =NULL;
	FILE* fp = NULL;
	fp  = fopen(argv[1],"r");
	if(fp == NULL)
	{
		perror("open file failed\n")//打开文件失败打印失败信息
 		return -1;//结束程序的执行
	}
	while(1)//逐行的循环读取数据
	{
		p =fgets(buf,10,fp);
		if(p = NULL)break;//此时文件已经读完,跳出循环
		if(buf[strlen(buf)-1] == '\n')//字符串的最后一位位‘\0’,所以所以换行符‘\n’在最后一位
		len++;//遇见'\n'行数+1
		bzero(buf, sizeof(buf));//每次使用完数据要把数据清空,防止下次使用出现错误的数据
		printf("len: %d\n",len);
	}
	return 0;
}

【3】按照指定大小读取
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
参数1:存放读取到的内容的首地址
参数2:读取的单位大小
参数3:读取的个数
参数4:流指针
返回值:成功 - 实际读取的字节数
读到文件尾 - 0

2)文件的操作
【1】按字符写入
int fputc(int c, FILE *stream);
int putc(int c, FILE *stream);
功能:向指定流中写入一个字符
参数1:写入的字符
参数2:流指针
返回值:成功 - 写入的字符
失败 - EOF
int putchar(int c); === fputc(c, stdout);
向标准输出流中写入一个字符

练习:使用fgetc和fputc编写一个程序,实现cp功能

#include<stdio.h>
int main(int argc, char *argv[])
{
	int ret;
	FILE *fp1 = NULL;//要拷贝的源文件的文件描述符
	FILE *fp2 = NULL;//要拷贝的目标文件的文件描述符
	if (argc < 3)
	{
		printf("输入的参数有错误");
		return -1;
	}
	fp1 = fopen(argv[1],"r");
	fp2 = fopen(argv[2],"w");
	if((fp1 == NULL)||(fp2 == NULL))
	{
		perroe("打开文件失败");
	}
	while(1)
	{
		ret = fgetc(fp1);
		if(ret == EOF)break;
		fputc(ret,fp2);
	}
	return 0;
}

【2】按行写入

int fputs(const char *s, FILE *stream);
int puts(const char *s); === fputs(s, stdout);
参数1:要写入的数据的首地址
参数2:流指针
返回值:成功 - 非0
失败 - EOF

练习:使用fgets和fputs编写一个程序,实现cp功能

# include <stdio.h>
# include <string.h>
int mian(int argc,char * argv[])
{
	char buf[10] = {10};
	char *p = NULL;
	FILE *fp1 = NULL;
	FILE* fp2 = NULL;
	if(argc < 3)
	{
		printf("输入参数错误");
		return -1;
	}
	fp1 = fopen(argv[1], "r");
	fp2 = fopen(argv[2], "w");
	if((fp1 == NULL)||(fp2 == NULL))
	{
		perror("打开文件失败");
		return -1;
	}
	while(1)
	{
		p = fgets(buf,10,fp1);
		if(p == NULL)break;
		fputs(buf,fp2);
		memset(buf,0,sizeof(buf));
	}
	return 0;
}

【3】按指定大小写入
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
参数1:存放写入的数据的首地址
参数2:写入数据的单位大小
参数3:写入的个数
参数4:写入的文件的流指针
返回值:成功 - 写入的字节数
失败 - 0
ret = fwrite(buf, 1, sizeof(buf), fp);

  1. 扩展学习
    【1】 出错处理
    errno - 是一个全局变量 #include <errno.h>
    void perror(const char *s);
    功能:输出错误信息
    参数:自定义的字符串 - 提示信息
    【2】关闭文件
    int fclose(FILE *fp);
    返回值:成功 - 0
    失败 - EOF
    fclose(fp);
    【3】修改文件指针位置
    int fseek(FILE *stream, long offset, int whence);
    参数1:流指针
    参数2:偏移量
    参数3:基准
    SEEK_SET:文件起始位置
    SEEK_CUR:文件当前位置
    SEEK_END:文件的结束位置
    返回值:成功 - 0
    失败 - -1
    【4】清空指定空间的数据

void bzero(void *s, size_t n); === memset(s, 0, n);

功能:给某个空间里的内容清0
参数1:要清0的空间的首地址
参数2:要清的空间的大小 - 字节

void *memset(void *s, int c, size_t n);
功能:给某块空间填充某个内容
参数1:要填充的空间的首地址
参数2:要填充的内容
参数3:要填充的空间的大小
返回值: s

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值