第9章 I/O库函数
系统调用是文件操作的基础,但它们至支持数据块的读/写。I/O库函数是一系列文件操作函数,既方便用户使用,又提高了整体效率。
I/O库函数与系统调用
- 系统调用函数:open()、read()、write()、lseek()、close();
- I/O库函数:fopen()、fread()、fwrite()、fseek()、fclose()。
I/O库函数算法
- fread算法
fread()函数用于从文件流中读取数据 - fwrite算法
fwrite()函数以二进制方式向文件流中写入数据
fread()从文件中读出n个字节保存到 buffer 中,而 fwrite()把 buffer中的n个字节写到文件中。最后,函数fread和fwrite的返回值为读或写的记录数。尽管 fread 和 fwrite 函数可以对数据进行成块读写,但并不是说一次想读写多少数据就能全部读写多少数据,毕竟缓存有限,而且不同的操作系统的缓存大小也可能不一样。 - fclose()算法
若文件以写的方式打开,fclose()会先关闭文件流的局部缓冲区,然后发出一个close(fd)系统调用来关闭FILE结构体中的文件描述符,最后释放结构体,将指针重置为NULL。
I/O库模式
模式参数 | 含义 | 模式参数 | 含义 |
---|---|---|---|
r | 读 | r+ | 读/写,不会截断文件 |
w | 写 | w+ | 读/写,会先截断文件;如果文件不存在,会创建 |
a | 加 | a+ | 通过追加进行读/写;如果文件不存在,会创建 |
- 字符模式I/O
- 行模式I/O
- 格式化I/O
- 内存中的转换函数
sscanf()和sprintf()并非I/O函数,而是内存中的数据转换函数。 - 其他I/O库函数
函数 | 功能 |
---|---|
fseek()、ftell()、rewind() | 更改文件流中的读/写字节位置 |
feof()、ferr()、fileno() | 测试文件流状态 |
fdopen() | 用文件描述符打开文件流 |
freopen() | 以新名称重新打开现有的流 |
setbuf() | 设置缓冲方案 |
popen() | 创建管道,复刻子进程来调用sh |
文件流缓冲
- 无缓冲
从非缓冲流中写入或读取的字符将尽快单独传输到文件或从文件中传输。例如,文件流stderr通常无缓冲。到stderr的所有输出都会立即发出。 - 行缓冲
遇到换行符时,写入行缓冲流的字符以块的形式传输。例如,文件流stdout通常是行缓冲,逐行输出数据。 - 全缓冲
写入全缓冲流或从中读取的字符以块大小传输到文件或从文件传输。这是文件流的正常缓冲方案。
文件操作是什么?
程序运行产生的数据是存储在内存中的,当程序关闭的时候,数据随之丢失,想要保存数据,需要进行文件操作将数据保存在磁盘中。
二进制文件和文本文件如何转换?
标准I/O库中主要使用 fread/fwrite来读写二进制文件,而对于文本文件可以使用 fread/fwrite fgetc/fputc fprintf等,文本文件与二进制文件使用不同的编码方式,把一个数据以什么样的编码(字符还是值本身)存入文件是由用户主动选择的,也就是写入的接口选择,如果以二进制接口方式写入文件那么就是一个二进制文件,如果以字符方式写入文件就是一个文本文件了。既然有写入时候的编码也就会有读出的编码,只有两个编码对应才能读出正确的结果。