文件

在 C 语言中,流 (stream) 表示任意输入的源或任意输出的目的地。流是一个抽象的概念,它即可以表示存储硬盘上的文件,也可以表示网络端口或者打印设备。流这个概念可以很好地屏蔽硬件设备之间的差异,使得 C 语言可以像读写文件一样读写任意的设备

Linux哲学:一切皆文件

文件缓冲

仅仅了解抽象的概念是不够的,有时候我们还需要了解事物运行的机理。由于内存和硬件设备之间存在读写性能上的”鸿沟”,所以操作系统会在内存上为流设置缓冲区

缓冲区是以先进先出的方式管理数据的。缓冲区分为三种类型:

满缓冲。当缓冲区空时,从输入流中读取数据;当缓冲区满时,向输出流中写入数据。

行缓冲。每次从输入流中读取一行数据;每次向输出流中写入一行数据。

无缓冲。顾名思义,就是没有缓冲区

stdin标准输入流

stdout标准输出流

stderr标准错误流

标准流

C 语言对流的访问是通过文件指针实现的,它的类型为 FILE* 。并且在 <stdio.h> 头文件中提供了 3 个标准流。这 3 个标准流可以直接使用——我们不需要对其进行声明,也不用打开或者关闭它们。

文件指针 默认含义
stdin 标准输入 键盘
stdout 标准输出 屏幕
stderr 标准错误 屏幕

文本文件和二进制文件

C 语言支持两种类型的文件:文本文件和二进制文件。文本文件中存储的是字符数据,人类是可以看懂的;二进制文件中的数据,人类是看不懂的。

文本文件具有两个独特的性质:

文本文件有行的概念。文本文件被划分为若干行,并且每一行的结尾都以特殊字符进行标记。在 Windows 系统中,是以回车符和换行符 (\r\n) 进行标记的;在 Unix和 Macintosh 系统中是以换行符 (\n) 标记的。

早期的 Macintosh 是以回车符 (\r) 标记每一行的结尾的。

文本文件可能包含一个特殊的 “文件末尾” 标记。一些操作系统允许在文本文件的末尾使用一个特殊的字节作为标记。在 Windows 系统中,这个标记为 ‘\x1a’ (Ctrl+Z)。Ctrl+Z不是必需的,但如果存在,它就标志着文件的结束,其后的所有字节都会被忽略。大多数其他操作系统 (包括 UNIX) 是没有文件末尾字符。

使用 Ctrl+Z 的这一习惯继承自 DOS,而 DOS 中的这一习惯又是从 CP/M (早期用于个人电脑的一种操作系统) 来的。

在写入数据时,我们需要考虑是以文本形式存储还是以二进制的形式存储。比如,存储整数 32767,一种选择是写入字符 ‘3’, ‘2’, ‘7’, ‘6’, ‘7’,需要 5 个字节。

另一个选择是以二进制形式存储这个数,这种方法只需要两个字节。

文本形式可以方便人类阅读和编辑;二进制形式可以节省空间,并且转换效率高。

打开/关闭文件

f o p e n

读写文件之前,我们需要使用 fopen 函数打开文件。

1
FILE* fopen(const char* filename, const char* mode);

第一个参数是文件的路径,用来定位文件的;第二个参数表示是以何种模式打开文件的。如果无法打开文件, fopen 返回空指针

文件路径

文件路径分为两种,一种是绝对路径:从根目录 (或者盘符) 开始,一直到文件所在的位置,比如:”c:/project/test.dat”。另一种是相对路径:从当前工作目录开始,一直到文件所在的位置,比如:”in.dat”。

在实际工作中,我们一般使用相对路径 (Why?)。

便于移植

模式

模式的选择不仅依赖于后续对文件的操作,还依赖于文件是文本形式还是二进制形式。打开一个文本文件,可以使用下面一些模式:

自己看pdf

写模式和追加模式是不一样的。如果文件存在,写模式会清空原有的数据,而追加模式会在原有数据的后面写入新的内容。

f c l o s e

看pdf

读/写文件

前面介绍了如何打开和关闭文件,接下来我们来学习下如何读写文件。其中fgetc/fputc , fgets/fputsfscanf/fprintf是用来读写文本文件的; fread/fwrite 是用来读写二进制文件的。

f g e t c & f p u t c

看pdf