IO_FILE 基本概念

流的概念

1
在C中引入了流(stream)的概念。它将数据的输入输出看作是数据的流入和流出,这样不管是磁盘文件或者是物理设备(打印机、显示器、键盘等),都可看作一种流的源和目的,视他们为同一种东西,而不管其具体的物理结构,即对他们的操作,就是数据的流入和流出。这种把数据的输入输出操作对象,抽象化为一种流,而不管它的具体结构的方法很有利于编程,而涉及流的输出操作函数可用于各种对象,与其具体的实体无关,即具有通用性。

存储的目标(比如一个文件)当做水池,链接水池和外界的是水管,这个水管往水池里灌水,或者把水池里的水泵出来,形成“流”。

往里灌水(写文件)时,对于水管(流)来说,是“将水管里的水输出到水池里”,此时对于流来说是输出流;

往外排水(读文件)时,对于水管(流)来说,是“将水池里的水输入到水管里”,此时对于流来说是输入流。

流的分类

在C中流可分为两大类,即文本流(text stream)和二进制流(binary stream)。

文本流

所谓文本流是指在流中流动的数据是以字符形式出现。在文本流中,’\n’被换成回车CR和换行LF的代码0DH和0AH。而当输出时,则0DH和0AH本换成’\n’。

二进制流

二进制流是指流动的是二进制数字序列,若流中有字符,则用一个字节的二进制ASCII码表示,若是数字,则用一个字节的二进制数表示。在流入流出时,对\n符号不进行变换。例如2001这个数,在文本流中用其ASCII码表示为:‘2’ ‘0’ ‘0’ ‘1’,共占4字节。 但是在二进制流中为其二进制形式:00000111 11010001 用十六进制就是07D1。只占两字节。

操作系统如何标识一个流

FILE结构体

在操作系统内部,用一个结构体对象标识一个流,结构体对象里面记录了这个流的相关信息。 这个结构体的名字叫FILE。这个结构体有以下字段

  • 缓冲区类型
  • 当前读指针
  • 末尾指针

这样的结构体是操作系统帮我们创建的,而我们要操作这个结构体,就要知道这个结构体的位置,而FILE * 指针就是指向这个结构体的指针。当采用fopen 打开一个流时会返回一个指向流对象的指针,指针类型为FILE *

FILE指针

每个被使用的文件都在内存中开辟一个区域,用来存放文件的有关信息,这些信息是保存在一个结构体类型的变量中,该结构体类型是由标准IO库定义的,取名为FILE。FILE封装了系统调用中的文件描述符的概念,所以标准IO中的函数不会直接操作文件描述符。

标准I/O预定义的3个流

一个进程启动的时候,会打开三个流:

  • 标准输入 stdin
  • 标准输出 stdout
  • 标准出错 stderr

缓冲的概念

为什么设置缓冲

  • 从效率的角度考虑,避免频繁地呼叫系统调用(read、write);其次缓冲区大小的设置在不同OS上是有差别的,标准库为我们做了优化选择。
  • 从安全角度考虑:用户态到内核态的切换。频繁的切换是不安全的。

系统自动的在内存里面为每一个正在使用的文件开辟一个缓冲区,从内存向磁盘输出数据必须先送到内存缓冲区,装满缓冲区,在一起送到磁盘里面。从内存向磁盘读取数据,则一次从磁盘文件中将一批数据读到内存缓冲区中,然后再从缓冲区中将数据送到程序的数据区。

例如:需要将1024 个字节写到文件中去,每次写一个字节。
如果是文件IO,则要进行1024次 写操作,将1024个字节挪到内核,然后到磁盘。

如果使用标准IO的话,会现将数据写到缓冲区中,然后等到缓冲区慢了,或者刷新了缓冲区,才整体将这些数据写入磁盘。只执行一次写操作即可,一次数据挪动即可。