Linux学习笔记之标准IO

关于了解标准IO以及文件IO,首先我们通过以下简化的图了解一下文件系统的体系结构

 

 

系统调用:是操作系统提供的一组特殊接口,我们可以通过这一组接口,进行分配内存、创建进程、实现进程之间的通信等。

VFS:虚拟文件系统,是Linux文件系统对外的接口,一方面给用户空间的程序提供文件系统接口,另一方面还提供了内核中的一个抽象功能,实现不同文件系统在Linux下共存。一个实际的文件系统想被linux支持,就必须提供一个符合VFS标准的接口,才能与VFS协同工作,VFS不是实际操作系统,只是一种转换机制。它就是把各种具体的文件系统的公共部分抽取出来,形成一个抽象层,是系统内核的一部分,位于用户程序和具体的文件系统之间。

从图中我们知道,我们应用程序有两种方法对文件进行操作,一个是直接通过系统调用可以直接和内核进行交互,另一个是通过c库然后再通过系统调用对内核进行交互。

以下说一下文件IO和标准IO的区别

文件IO:又称为低级磁盘IO,任何兼容POSIX标准操作系统上都支持文件IO,每次执行操作时都会执行相关系统调用,不带缓冲,可以访问不同类型的文件。文件IO是对文件描述符进行操作

    优点:直接处理实际文件。

    缺点:频繁的系统调用,增加系统开销。

标准IO:又称为高级磁盘IO,遵循ANSIC相关标准,只要并发环境中有标准C库,标准IO就可以使用,带缓冲,通常只能访问普通文件。标准IO是对流进行操作。

    优点:先读写缓冲区,然后必要时访问实际文件,减少系统调用,移植性好。

 

 

一.标准IO

 

  标准IO是通过流进行操作从而达到对文件进行操作,那么流究竟是什么呢?

  流其实是一个结构体类型的指针,一个指向文件的指针,是可以被我们当作操作文件的入口,以下是在/usr/include下找到流的原型

  ---------------------------------------------------------
    补充:安装ctags插件
    sudo apt-get update
    sudo apt-get install ctags
    cd /usr/include
    sudo ctags -R 使ctags在当前目录下生效
    vim -t 查找内容
  ---------------------------------------------------------

        

 

 

 

 

 

 

 

 

 上面的结构体就是流的原型,所以我们在使用标准IO操作文件时用到的就是流。

标准IO下流的三种缓冲类型:

  全缓冲:存满标准IO的缓冲区后才进行实际IO操作。默认打开都是全缓冲的。

      何时能操作实际IO?

      (1)缓冲区满

      (2)使用fflush函数

      (3)程序正常结束

  行缓冲:输入输出遇到换行符时执行实际IO操作。例子:标准输入流和标准输出流。

      何时能操作实际IO?

      (1)缓冲区满

      (2)使用fflush函数

      (3)程序正常结束

      (4)遇到换行符

  无缓冲:不对IO操作进行缓冲,即在流读写时会立刻操作实际文件。例子:标准错误流。

  

流的常见操作:打开、读写、关闭

  
  用户程序进行时,系统默认生成三个流,标准输入流(stdin)、标准输出流(stdout)、标准错误流(stderr)。

  流的打开:有fopen()、freopen()、fdopen(),以不同形式打开文件,并且返回值都是一个指向流的指针,接下来主要讲fopen。

  

  函数原型:FILE *fopen(const char *path, const char *mode);

  函数功能:打开文件

  函数头文件:#include <stdio.h>

  函数参数:path:文件所在路径

       mode:文件打开方式        

          r:用只读的方式打开,文件要一定存在
          r+:可以对文件进行读写,文件要一定存在
          w:用只写的方式打开,文件可以不存在,如果不存在,则创建文件,如果文件存在,就清空文件中的内容  
          w+:可以对文件进行读写,文件可以不存在,如果不存在,则创建文件,如果文件存在,就清空文件中的内容
          a:用只写的方式打开,文件可以不存在,如果不存在,则创建文件,如果文件存在,在文件末尾追加
          a+:可以对文件进行读写,文件可以不存在,如果不存在,则创建文件,如果文件存在,在文件末尾追加

  函数返回值:成功:返回流(指向FILE的指针)

        失败:返回NULL

 

  流的关闭:fclose(),执行这个函数时总共进行两个步骤    ①将流的缓冲区内数据全部读入写入文件中     ②释放相关资源,关闭流

   

  函数原型:int fclose(FILE *fp);

  函数功能:关闭文件

  函数头文件:#include <stdio.h>

  函数参数:fp:准备关闭的流

  函数返回值:成功:返回0

        失败:返回EOF(-1),并置错误码

 

 

 

   注:当标准IO执行结果如果出现错误时,会把错误码保存在全局变量errno中,然后使用perror函数进行打印错误信息。

  

 

  流的读写:流的读写可以分做三小块,①fgetc和fputc   ②fgets和fputs  ③fwrite和fread

  ①fgetc和fputc   按字符读写(看最后一个字母就知道啦 c代表char)

    

  函数原型:int fgetc(FILE *stream);

  函数功能:从文件中读取一个字符

  函数头文件:#include <stdio.h>

  函数参数:stream:要读取的流;

  函数返回值:成功:返回读到的字符

        读到文件末尾或者失败:返回EOF(-1),并置错误码

    

 

     fgetc内部会强转,所以最后返回的时字符。

 

  函数原型:int fputc(int c,FILE *stream);

  函数功能:向指定流输出一个字符

  函数头文件:#include <stdio.h>

  函数参数:

      c : 需要输出的字符

      stream:要指定的流;

  函数返回值:成功:输出字符c

        失败:返回EOF(-1)

 

 

fgetc和fputc结合起来使用文件复制代码如下

 

 

 

 

 

②fgets和fputs   按字符读写(看最后一个字母就知道啦 s代表string)

 

 

  函数原型:int fgets(char *s , int size , FILE *stream);

  函数功能:从流中读取取一行字符串,最多读取size-1字符。因为最后一个字符要放'\0',如果遇到换行符,则停止一次读取

  函数头文件:#include <stdio.h>

  函数参数:

      s: 用来存放从文件中读取到的字符串缓冲区首地址

      size : 获取的字符数(读取到最多为size -1)

      stream:要指定的流;

  函数返回值:成功:返回s

        到达文件末尾或者失败:NULL

 

当一行内容大于等于size-1时,就读size-1个字符 ,否则读到换行符结束 

 

 

  函数原型:int fputs(const char *s , FILE *stream);

  函数功能:向文件每次输入一行字符串

  函数头文件:#include <stdio.h>

  函数参数:

      s: 用来存放从文件中读取到的字符串缓冲区首地址

      stream:要指定的流;

  函数返回值:成功:返回s

        失败:NULL

 

 

fgets和fputs结合起来使用文件复制代码如下

 

posted @ 2020-09-03 10:10  許家那颗葱  阅读(127)  评论(0)    收藏  举报