小结
概念
■ 与面向标准输入输出设备的输入、输出相比,面向文件的输入、输出要多两个步骤:打开文件和关闭文件。
■ 打开文件可以通过调用fopen()函数实现。
■ 关闭文件可以通过调用fclose()函数实现。
■ 所谓“打开”是指建立内存与外部设备间的联系通道,建立内存缓冲区等。所谓“关闭”则是关闭内存与外部设备间的联系通道,清除内存缓冲区等。
■ C代码中操作文件的指针为“FILE *”类型。
■ “FILE”这种数据类型在“stdio.h”文件中定义。
■ 打开文件的模式有"r"、"w"、"a"、"r+"、"w+"、"a+"、"rb"、"wb"、"ab"、"r+b"、"w+b"、"a+b"、"rb+"、"wb+"、"ab+"这几种。
■ 打开文件时不但应该清楚文件的名称,还应该明确文件的位置。
■ 打开文件时应该考虑到存在无法打开文件的可能性。
■ exit()函数的功能是退出程序运行,并向程序调用者返回一个标志程序结束状态的“int”类型的数据。该函数的原型在“stdlib.h”中描述。
■ 调用exit()函数直接结束程序运行,并不返回main()。
■ fprintf()、fputs()、fputc()是与printf、puts()、putchar()相对应的面向文件的输出函数。
■ fscanf()、fgets()、fgetc()是与scanf()、gets()、getchar()相对应的面向文件的输入函数。
■ 格式化输入、输出的转换说明中的各个组成部分必须遵守严格的次序。
■ C语言程序的输入与输出对象被统一地称为文卷(File),可以是磁盘文件,也可能是一些具体的物理设备,比如显示器、键盘或打印机等。
■ 流(stream)是程序输入、输出的直接对象,但流只是一个逻辑上的抽象概念。流可以被理解为一个连续的具有方向性的字节序列。由于流这个概念,C程序的输入与输出的外部接口得到了统一和规范化。流的两端分别是程序和外部文卷。
■ C语言支持两种数据流:文本流(Text Streams)和二进制流(Binary Streams)。
■ 代码通过“FILE *”类型的指针实现对外部文卷的操作,代码本身并不需要为这种指针所指向的具体数据对象提供存储空间。
■ 文本流中的字符序列并不一定与其在外部环境中的表示完全一致。
■ 二进制流是对内存中数据项原封不动的映射或复制。
■ C语言规定,程序至少能同时打开8个文卷。
■ 程序运行时,stdin、stdout和stderr这3个文本流是自动打开的。
■ stdout和stderr对应的文卷一般都为标准输出设备。但通常stdout是缓冲流,而stderr是非缓冲流。
■ EOF是在“stdio.h”文件中定义的一个int类型的符号常量,这个值常常被用来作为I/O函数在某些特定情况下的返回值。
■ fwrite()函数和fread()函数面向的是二进制流。
■ feof()函数用于判断读入输入流时是否遇到了文件结尾,它只有在流结尾之后读数据的情况下才能判断出是否到了文件的结尾。
■ ferror()函数用于判断读写失败是否是因为发生了错误,它只有在读写失败之后才能作出这个判断。
■ 在Windows或DOS操作系统下,文本流中的'\n'与文本文件中的'\0xd'、'\0xa'相对应,且流中的'\0x1a'被视为流的结束标志。
■ ftell()函数可以求得文件的当前操作位置。
■ fseek()函数用于设置已经打开的“stream”流的操作位置,对于文本流,这个位置只能是相对于开头位置的值。
■ rewind()函数用于将操作位置重新置为文件的开头。
■ fgetpos()函数和fsetpos()函数用于针对大文件求出或设置文件的当前位置。
常见错误
■ 不写明文件包括所在盘符、路径在内的全名,自己也不清楚数据被写到哪里了。
■ 忘记写文件的扩展名。
■ 把文卷名写错。例如把C:盘根目录下的new.txt写成"C:\new.txt"。对于C语言来说字符串字面量中的“\n”是一个字符。
■ 误用"w"或"wb"方式打开一个已经存在的文件,造成数据丢失。
■ 代码中没有考虑到磁盘写保护或磁盘容量不足等情况。
■ 使用fwrite()或fread()函数操作文本文件,使用fprintf()或fscanf()函数操作二进制文件。
风格
■ 应该及时关闭不再使用的文件,否则会占用资源,造成程序效率低下。
牛角尖
■ 对于
char s[80];
gets(s);
由于存在输入字符多于80个时,超出s数组存储空间的可能性,而使用
fgets(s, 80, stdin);
输入数据显然不存在这种顾虑,因此后者更安全。