[TOC] 记录下,了解概念。
描述程序与文件连接
- 文件描述字
- 流 系统中关于I/O的函数也分为两大类:文件描述子操作,流操作。
当用流或文件描述字I/O函数打开一个文件时,分别返回一个流或文件描述字,后面就可以将这个流或文件描述字作为参数交给相应读写函数来完成实际的读写操作。通过关闭文件可以终止程序与文件的连接。
文件描述字与流
文件描述字表示为int类型的对象,流表示指向类型为FILE结构的指针。文件描述字多数是系统调用,提供底层基本的输入输出操作接口。
流函数建立在文件描述字之上,通过文件描述字函数而实现,给程序提供更高一级的输入输出接口。流函数比对应的文件描述字函数更丰富,功能更强大,也更利于程序的移植。
一般情况下,坚持使用流函数,系统基本支持流函数,而不是所有系统支持文件描述字。除非做些特殊操作,而此操作只能使用文件描述字,如需要对特定设备进行控制操作,非阻塞输入等。
流和FILE对象
流的数据类型是FILE类型。FILE对象由标准I/O库函数内部分配和管理,用户无需自己创建FILE类型对象,无须查看FILE对象内容,调用标准I/O库函数即可,如fopen()打开或创建一个流时,它会返回一个指向FILE结构的指针,此时程序和文件之间建立了一个流。
标准流
UNIX系统中每个进程都有三个预先定义并自动打开的流,stdin,stdout,stderr。这三个标准流在< stdio.h >中说明,分别代表标准输入、标准输出和标准错误输出。
打开和关闭流
三个函数
freopen()重新打开pathname指定的文件,作用类似于fclose()和fopen()的合并。
读和写流
打开一个流,就可以对其进行读写。使用I/O函数: 如:字符I/O 每次读入一个字符: 输出单字符:
其它函数不做细究。
流缓冲
每一个流都有一个输入输出缓冲区。写入流的字符并不立即写到文件中,而是现在缓冲区中聚集为一块,然后异步地以块为单位传送到文件。
目的:减少调用低级I/O函数(如read(),write())的次数,因为真正读写文件的函数是系统调用,它们是较费时间的操作。
举例: 对于存储在硬盘上的文件,当进 程用read或 write(读写数据时,设备驱动程序必须将数据在文件中的地址转换成硬盘的物理磁 道号、卷宗号以及扇段号。之后设备必须移动磁头至相应的卷宗并等待磁盘的相应扇段旋转至 磁头之下。一切准备好了之后才能从磁盘开始读写数据。显然,每读写一个或几个字符便导致 执行这一串的动作是极不合算的。利用缓冲处理则不必为每读写一个字符而频繁地与外部设备 打交道,同时还可以实现异步IO,即在CPU运行程序的同时从外设传输数据,从而提高输入输出的效率。
流有三种缓冲类型:
- 全缓冲 磁盘文件一般是全缓冲
- 行缓冲 一般用于终端之类交互设备的流
- 无缓冲 不设置缓冲区。
UNIX对新打开的流采用如下默认缓冲类型:
- 标准错误刘总是无缓冲的。 尽快返回错误
- 其他的流若引用交互设备则是行缓冲的,否则是全缓冲。 这是自动默认,使用时也可自己设定。
格式输出
格式输入
思考:
- 打开文件的实质是什么?
- 从应用的角度看,UNIX系统中程序与文件建立连接有几种机制?流与文件描述字有什么 区别?
- 什么是文件位置?它起什么作用?
- 系统为每一个进程自动打开的输入输出流有哪些?它们对应的名字是什么?
- 写“r”方式打开的文件会发生什么情况?读“w方式打开的文件呢?建议你编写一个这样 的程序试试。
- 按读写数据的粒度分,有几类流输入输出函数?
- 说说PHP关于缓冲区的处理。
参考: php缓冲区详解