第5章 标准IO库

第五章 标准I/O库

5.2 流和 FILE 对象

  • 普通 I/O,文件描述符与文件关联
  • 标准 I/O,流(stream)与文件关联

流的定向决定是单字节流还是 多字节流(宽)
两个函数可以改变流的定向 fwidefreopen

  • fwide
#include <wchar.h>
int fwide(FILE *stream, int mode);

mode参数:

  • 参数为负:fwide 将试图指定流是字节定向
  • 参数为正:fwide 将试图指定流是宽定向
  • 参数为 0:fwide 不设置流的定向,返回标识该流定向的值

返回值:

  • 宽定向:“+”
  • 字节定向: “-”
  • 未定向: 0

fiwde 不改变已定向流的定向,且无出错返回。在调用前清除 errno,返回值时检查 errno 的值,通过 errno 的值来判断成功还是失败。

FILE 对象

fopen 打开一个流时,返回一个 FILE 对象的指针,FILE 对象是一个包含了流的所有信息的结构,包括文件描述符、缓冲区指针、缓冲区长度、缓冲区字符数及出错标志等。

5.3 标准输入、标准输出和标准错误

流与文件的对应方式,与文件描述符与文件的对应方式相似。
头文件:<stdio.h>

文件I/O 标准I/O
输入 STDIN_FILENO stdin
输出 STDOUT_FILENO stdout
错误 STDERR_FILENO stderr

5.4 缓冲

目的: 减少使用 readwrite 调用的次数,自动对每个 I/O 流进行缓冲管理。

全缓冲

标准 I/O 填满缓冲区后才进行实际的 I/O 操作。磁盘上的文件就是这样。流第一次进行I/O操作时使用 malloc 获得缓冲区。

冲洗(flush):缓冲区的写操作。缓冲区可由程序自动冲洗,也可调用 fflush 手动冲洗一个流。

flush两种含义:

  1. 将缓冲区内容写到磁盘
  2. 清除缓冲区中数据
行缓冲

在输入和输出中遇到换行符,才执行I/O操作,比如 fputc 一次输出一个字符,但只有在写了一行之后才进行实际I/O操作。终端通常使用行缓冲

限制:

  1. 每一行缓冲区长度固定,缓冲区满,没有换行符也进行I/O操作
  2. 从不带缓冲的流,或者行缓冲的流获取数据,冲洗所有行缓冲输出流
不带缓冲

标准I/O库不对字符进行缓冲存储。例如,用 fputs 写15个字符到不带缓冲流中,字符立即输出。可能使用 write 直接写入相关文件中。
stderr 通常不带缓冲。

通常情况:

  • stderr 是不带缓冲的
  • 指向终端设备的流,是行缓冲,否则是全缓冲
更改缓冲类型
#include <stdio.h>
void setbuf(FILE *stream, char *buf);
int setvbuf(FILE *stream, char *buf, int mode , size_t size);
  • setbuf

关闭或打开缓冲机制。带缓冲(全缓冲,如果终端设备,可以为行缓冲)时,buf 指向长度为 BUFSIZ (定义在 <stdio.h> ) 的缓冲区;关闭缓冲,buf 设置为 NULL

  • setvbuf

利用 mode 参数,精确说明需要使用的缓冲类型。

  • 二者区别
函数 mode buf 缓冲区及长度 缓冲类型
setbuf 非空 长度为 BUFSIZ 的用户缓冲区 buf 全缓冲或行缓冲
NULL 无缓冲区 不带缓冲
setvbuf _IOFBF 非空 长度为 size 的用户缓冲区 buf 全缓冲
NULL 合适长度的系统缓冲区 buf
_IOLBF 非空 长度为 size 的用户缓冲区 buf 行缓冲
NULL 合适长度的系统缓冲区 buf
_IONBF (忽略) 无缓冲区 不带缓冲

自动分配的 size 长度的值通常是常量 BUFSIZ 指定的值。

注意

  • 如果在一个函数内分配一个自动变量类的标准I/O缓冲区,则从函数返回之前,必须关闭该流。
  • 缓冲区的一部分还用来存放实现自己的管理操作信息,所以存放在缓冲区的实际字节数少于 size
  • 一般应由系统选择缓冲区的长度,并自动分配缓冲区。这种情况下关闭流,标准I/O库自动释放缓冲区。
强制冲洗一个流
  • fflush
#include <stdio.h>
int fflush(FILE *stream);

返回值

  • 成功:0
  • 失败:EOF 并 设置 errno

此函数使流所有未写的数据传送至内核,作为例外,如果 fpNULL ,则将导致所有的输出流被冲洗。
fflush 仅仅刷新用户空间的由 C 库 提供的缓冲。要保证数据被物理地存储到磁盘上,必须也刷新内核缓冲。例如,使用 sync(2)fsync(2)

5.5 打开流

#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);
FILE *fdopen(int fd, const char *mode);
FILE *freopen(const char *pathname, const char *mode, FILE *stream);

参数

mode 描述 open(2)对应标志
r / rb 读方式,流指向文件开始位置 O_RDONLY
w / wb ,将文件长度截断至0,如果不存在,则创建文件,流指向文件开始位置 O_WRONLY | O_CREAT | O_TRUNC
a / ab ,追加(文件尾),不存在则创建文件,流指向文件末尾 O_WRONLY | O_CREAT | O_APPEND
r+ / r+b / rb+ 读、写,流指向开始位置 O_RDWR
w+ / w+b / wb+ 读、写,将文件长度截断至0,如果不存在,则创建文件,流指向开始位置 O_RDWR | O_CREAT | O_TRUNC
a+ / a+b / ab+ 读、写, 如果文件不存在,则创建文件,读文件从开始读,写文件则追加至文件尾 O_RDWR | O_CREAT | O_APPEND

打开二进制文件时使用 b ,在区分文本文件二进制文件的系统中可以使得文件以合适的方式打开。但是在 UNIXLinux 等遵循 POSIX 的系统中,对两种文件不进行区分,b 都被自动忽略。如果为了良好的可移植,最好加上 b

返回值

  • 成功:返回指向文件的 FILE 对象指针
  • 出错:返回 NULL
fopen

打开 pathname 指向的一个文件,并与一个流关联

fdopen

将一个流关联到已经存在的文件描述符 fd打开模式(mode)必须与文件描述符 fd 的 open 模式相匹配,流的定为与 fd 的偏移量相同,错误和文件结束标记被清除。ww+ 打开的文件也不被截断,文件描述符不会被复制(dup),在关闭由 fdope

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值