任意输入的源或任意输出的目的地叫做流。
流
文件指针
C 程序中对流的访问是通过 文件指针 来实现的,如果程序除了标准流之外还需要两个流,可以包含如下声明:
|
|
该结构(类型)在
|
|
注意到了这个结构体的 tag 了吗——_iobuf
,定义了文件的缓冲区大小、缓冲区位置、访问模式、文件描述等信息。
标准流和重定向
可以直接使用的 3 个标准流:stdin
, stdout
, stderr
。
输入重定向
|
|
输出重定向
|
|
总结
把符号看成一个漏斗,大的是起点,小的是终点。
|
|
文本文件与二进制文件
文本文件
字节表示字符。
文本文件分为若干行。每一行通常以一两个特殊字符结尾。Windows 中,是回车和紧跟其后的换行符,分别为 '\x0d'
, '\x0a'
在 类 UNIX 系统中,行末是单独的回行符,旧版 Mac OS 使用单独的回车符。
包含特殊的“文件末尾”标记。在 Windows 中,标记为 '\x1a'
(Ctrl+Z)
二进制文件
编写用来读写文件的程序时,需要考虑该文件是文本文件还是二进制文件。
在屏幕上显示文件内容的程序可能要把文件视为文本文件。但是,文件复制程序就不能认为要复制的文件为文本文件。
如果那样做,就不能完全复制含有文件末尾字符的文本文件。在无法确定文件是文本形式还是二进制形式时,安全的做法是把文件假定为二进制文件。
文件操作
打开文件
Windows 中不要使用绝对路径分隔符 \
(会被认为是转义字符),使用相对路径分隔符 /
|
|
永远不要假设每次都能打开文件,每次都必须要测试 fopen 函数的返回值以确保不是空指针。
模式
用于文本文件的模式字符串
模式字符串 | 含义 |
---|---|
“r” | 打开文件用于读 |
“w” | 打开文件用于写(文件不需要存在) |
“a” | 打开文件用于追加(文件不需要存在) |
“r+” | 打开文件用于读和写,从文件头开始 |
“w+” | 打开文件用于读和写,如果文件存在就截去 |
“a+” | 打开文件用于读和写(如果文件存在就追加) |
二进制文件与之类似,但是需要在模式字符串中包含字母 b
,例如 "rb"
关闭文件
fclose()
关闭不再使用的文件,参数是文件指针。如果成功关闭了文件,函数返回零,否则返回错误代码 EOF
。对文件的输入/输出操作都是在缓冲区中进行的,写入文件的数据可能还没有真正地写到磁盘中,而是在内存的缓冲区中,如果不执行关闭文件操作,可能会使部分数据未保存到文件中。
|
|
示例
|
|
当然,也可以:
|
|
从命令行获取文件名
|
|
临时文件
|
|
不要过于频繁地调用 tmpnam()
。
文件缓冲
|
|
其他文件操作
|
|
以上两个函数对文件名而不是文件指针进行处理,如果调用成功,这两个函数都返回零;否则,都返回非零值。
|
|
如果打开了要改名的文件,那么一定要保证在调用 rename()
之前关闭此文件。对打开的文件执行改名操作会失败。
格式化输入/输出
|
|
在 C 程序中测试 scanf()
的返回值的循环很普遍,如下,在首个遇到问题的符号处停止:
|
|
…scanf 格式串
- 转换说明。大多数转换说明 (%c, %n 例外 ) 会跳过输入项开始处的空白字符。但是,转换说明不会跳过尾部的空白字符。但是,转换说明不会跳过尾部的空白字符。
- 空白字符。该中函数格式串中的一个或多个连续的空白字符与输入流中的零个或多个空白字符相匹配。
字符的输入/输出
|
|
进行文件的复制操作。
|
|