IO入门day1

14 篇文章 0 订阅

课程分为三部分:IO文件-动态库、静态库制作,进程(本地进程间通信),线程(线程通信)

特点:学习大量的函数接口调用-函数名及功能、man手册查看参数

一、IO介绍

1、概念

对文件的输入输出。I :input  O:output

读文件:将文件中的内容读到内存中进行处理

写文件:将内存中的内容写到文件中

文件是存放到磁盘空间上的,掉电文件不丢失

2、linux文件类型:

b(块设备文件)

c(字符设备文件)

d(目录文件)

-(普通文件)

l(链接文件)

s(套接字文件)网络编程

p(管道文件)

二、文件IO和标准IO区别

总结:

   标准IO:是c库提供的输入输出函数接口。不同的操作系统都可以使用,只要有库就行。是在系统调用之前做了一个二次封装,间接进行了系统调用。

          文件IO:内核向上提供的输出输出函数接口,叫做系统调用函数接口。基于内核,内核不同,系统调用函数接口不同,文件IO不同操作系统函数接口不通用。

fread-标准IO的函数接口
{
    if(是linux)
    {
        //调用linux的系统调用函数接口
        read();
    }
    else if(是windows)
    {
         _read();
    }
    else if(是mac)
    {
        Read();
    }
}
标准IO在系统调用之前做二次封装增加缓存机制 ,减少了系统调用次数,提高效率。

  • 三、标准IO

 1.标准I/O

    标准IO是指在C库中提供的一组专门用于输入输出的函数

    标准I/O由ANSI C标准定义不仅在UNIX系统,在很多操作系统上都实现了标准I/O

    标准I/O通过缓冲机制减少系统调用,实现更高效率

 标准I/O库的所有操作都是围绕流(stream)来进行的,在标准I/O中,流用FILE *来描述。

    标准IO默认打开了三个流:stdin、stdout、stderr-->标准输入、标准输出、标准出错 

 2. 文件 I/O   man 2  

是有linux内核提供的接口函数

这些操作往往都会涉及到 对硬件的操作,

磁盘运行速度比较慢,因此要减少磁盘的

读写次数,没有缓冲机制。

增加每次续写的量 ,也就是减少 

read write 函数的调用次数。

四、流

 定义:所有的I/O操作仅是简单的从程序移进或者移出,这种字节流,就称为流。

   分类:文本流/二进制流。

  流指针:FILE *

每个被打开的文件都在内存中开辟一个区域,

用来存放文件的有关信息,这些信息是保存在一个

结构体类型的变量中,该结构体类型是由系统定义的,

取名为FILE。 

查看结构体:FILE       追踪软件ctags

    vi   -t    FILE  

typedef struct  _IO_FILE FILE; 

   ctrl  ’]‘  :追踪

   ctrl  ’t‘ :返回:

用结束地址减去起始地址可以得到缓存区大小:

  char* _IO_buf_base;   /* 缓存区的起始地址 */

          char* _IO_buf_end;    /* 缓存器的结束后地址 */

围绕“流”进行操作,“流”用FILE*表示。 

  • FILE是数据类型(结构体),FILE*结构体指针。
  • 文件内部有文件指针,文件用文件指针操作,流只是起到了一个媒介的作用,封装原来的接口等,开辟缓冲区,减少系统调用。
  • 索引使用:1.vi -t要查找的内容 (查找宏,数据类型等)

输入前面序号,回车

  1. 继续追踪

将光标定位到要追踪的内容上,ctrl+] (右中括号)

回退:ctrl+t

3)标准IO默认打开了三个流,stdin(标准输入)、stdout(标准输出)、stderr(标准错误)

三个流是结构体指针变量。

4)标准IO一般只用于操作普通文件

五、标准I/O常见函数

1. fopen / fclose  打开文件 关闭文件 

2. fgetc / fputc   读一个字符/写一个字符

3. fgets / fputs   读一个字符串/写一个字符串

4. fwrite/ fread   读写一个二进制文件

5. fseek     移动文件指针(光标)函数

  • 六、缓冲区分类

注意:缓存区是在使用的时候才会开辟

   1.全缓存  -->fopen打开的文件都是全缓存

   刷新全缓存:

1.程序正常退出

  2.fflush强制刷新缓存

  3.遇到return (main)

  4.exit退出进程

  5.关闭fclose流指针

  6.缓存区满

   2.行缓存  -->基于终端:stdin\stdout

     刷新缓存区:

  1.'\n'刷新

  2.程序正常退出

  3.fflush强制刷新缓存

  4.遇到return (main)

  5.exit退出进程

  6.关闭fclose流指针

7.缓存区满

 注意:当遇到阻塞输入函数时,输出缓存区会刷新       

   3.不缓存:  stderr  

行缓存区大小计算:

#include <stdio.h>
#include <unistd.h>

int main(int argc, char const *argv[])
{
 //计算行缓存的大小   
   /*  for(int i=1;i<300;i++)//256*4=1024 = 1KB
    {
      printf("%4d",i);
    }*///缓存区满计算
  //缓存区首尾地址之差
    printf("hello world.");//缓存区使用时开辟
    printf("size:%d\n",stdout->_IO_buf_end-stdout->_IO_buf_base);
    while(1);
    return 0;
}

fflush函数:

查看错误码  vi -t EEXIST

#include <stdio.h>
int fflush(FILE *stream);
功能:刷新缓存区
参数:
    stream:流  (NULL:刷新所有流)
返回值:成功 0
失败:返回错误码 EOF(-1),更新errno。

七、缓冲机制

1)全缓冲:跟文件相关

刷新条件:

程序正常结束

缓冲区满刷新

强制刷新:fflush

2)行缓冲:跟终端相关

刷新条件:

\n

程序正常结束

缓冲区满刷新

强制刷新:fflush

#include <stdio.h>

int main(int argc, char const *argv[])
{
    //1.\n刷新缓冲区
    // printf("hello world\n");

    // while (1)
    //     ;
    //2.程序正常退出
    // printf("hello world");

    // while (1)
    //     ;//不让程序结束
    //3.缓冲区满刷新
    //有大小,当将缓冲区写满数据时,
    //再继续向缓冲区中写数据,
    //会将原来缓冲区中满了的数据全部拿出来,打印到终端
    //新写的数据,可以继续向里面写
    //测试缓冲区大小 kb 1kb=1024byte 1b=8bit
    //缓冲区大小1kb
    //方法一:
    // for(int i=0;i<300;i++)
    // {
    //     printf("%4d",i);
    // }
    // while(1);
    //方法二:
    //缓冲区的结束地址-起始地址=缓冲区大小
    // printf("hello"); //开辟缓冲区
    // printf("%d\n", stdout->_IO_buf_end - stdout->_IO_buf_base);
    // 4.强制刷新
    printf("hello");
    //fflush(stdout);//强制刷新
    fflush(NULL);//强制刷新所有的输出缓存
    while (1)
        ;
    return 0;
}

return 是函数的正常结束

ctrl +c是函数的不正常结束

3)不缓冲:没有缓冲区,标准错误

scanf--》标准输入缓冲区---》终端输入

标准输入缓冲区有内容 不进入终端输入

printf--》标准输出缓冲区---》终端

  • 八、标准IO函数接口

1fopen  freopen打开文件

1)fopen 打开文件

FILE *fopen(const char *path, const char *mode)
功能:打开文件
参数:
    path:打开的文件路径
    mode:打开的方式
        r:只读,当文件不存在时报错,文件指针定位到文件开头
        r+:可读可写,当文件不存在时报错,文件指针定位到文件开头
        w:只写,文件不存在创建,存在清空文件,文件指针定位到文件开头
        w+:可读可写,文件不存在创建,存在清空文件,文件指针定位到文件开头
        a:追加(在末尾写),文件不存在创建,存在追加,文件指针定位到文件末尾
        a+:读和追加,文件不存在创建,存在追加,读文件指针定位到文件开头,
            写文件流定位到文件末尾
注:当a的方式打开文件时,写只能在末尾进行追加,定位操作是无法改变写的位置,但是可以改变读的位置
返回值:成功:得到一个文件流指针
      失败:NULL,并且会设置错误码

a+:初始读指针在文件开始位置,写指针在文件结束位置,如果只调用读指针,那么读指针从刚开始位置后移,一旦调用写指针,读写指针合二为一,读指针去到写指针的位置

测试:一个任务中最多能打开多少个文件?(一个文件是可以被重复打开)1024个;

  1. 2、获取错误信息 perror 

2.1查看错误码  vi -t EEXIST

void perror(const char *s);
功能:根据errno值获取错误信息,将信息输出到终端
参数:
    s:错误信息的内容
返回值:无

  1. 3、关闭文件:fclose

int fclose(FILE* stream);
功能:关闭文件
参数:stream:文件流
成功:返回0
失败:返回-1,更新erron

4、读写操作

1)fgetc:每次读一个字符

int  fgetc(FILE * stream)
功能:从文件中读取一个字符
参数:stream:文件流
返回值:成功:读到的字符ASCII码
      失败或读到文件末尾:EOF(-1)

2)fputc:每次写一个字符

int fputc(int c, FILE * stream)
功能:向文件中写入一个字符
参数:c:要写的字符
   stream:文件流
返回值:成功:写的字符的ASCII
      失败:EOF-1

练习1、用fgetc和fputc完成cp功能

练习2、测试全缓存大小

3)fprintf定向输出到文件中

int fprintf(FILE *stream, const char *format, ...);
    功能:向指定的文件以指定的格数写入数据
	  参数: stream :流指针
	    format:指定格式
		...:多个参数
	返回值:输出字符个数
	 失败返回:EOF


4)fgets:

char * fgets(char *s,  int size,  FILE * stream);
功能:从文件中每次读取一行字符串
参数:s:存放字符串的地址
         size:一次读取的字符个数         
         stream:文件流
 返回值:成功:s的地址
       失败或读到文件末尾:NULL
特性:每次实际读取的字符个数为size-1个,会在末尾自动添加\0
       每次读一行,遇到\n后不再继续,读下一行

5)fputs

 int fputs(const char *s, FILE *stream);
   功能:向指定文件中输入一串字符
   参数:
         s:输入字符串的首地址
		 stream:文件流指针
	返回值:成功返回输出字符个数
	失败返回EOF

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

满山的猴子我的腚最红

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值