函数——
fopen()
、getc()
、putc()
、exit()
、fclose()
、fprintf()
、fscanf()
、fgets()
、fputs()
、rewind()
、fseek()
、ftell()
、fflush()
、fgetpos()
、fsetpos()
、feof()
、ferror()
、ungetc()
、setvbuf()
、fread()
、fwrite()
;如何使用C标准I/O系列的函数处理文件;
文件模式和二进制模式、文本和二进制格式、缓冲和无缓冲I/O;
使用既可以顺序访问文件也可以随机访问文件的函数。
1 与文件进行沟通
1.1文件是什么
**文件**通常是在磁盘或固态硬盘上的一段已命名的存储区。
1.2文本模式和二进制模式
导入:
C把文件看作是一系列连续的字节,每个字节都能被单独读取。这与
UNIX
环境中(C的发源地)的文件结构相对应。由于其他环境中可能无法完全对应这个模型,C提供两种文件模式:文本模式和二进制模式。
区分文本内容和二进制内容、文本文件格式和二进制文件格式,以及文件的文本模式和二进制模式:
所有文件的内容都以二进制形式(
0
或1
)存储。但是,如果文件最初使用二进制编码的字符(例如,ASCII或Unicode)表示文本(就像C字符串那样),该文件就是文本文件,其中包含文本内容。如果文件中的二进制值代表机器语言代码或数值数据(使用相同的内部表示,假设,用于long
或double
类型的值)或图片或音乐编码,该文件就是二进制文件,其中包含二进制内容。为了规范文本文件的处理,C提供两种访问文件的途径:二进制模式和文本模式。在二进制模式中,程序可以访问文件的每个字节。而在文本模式中,程序所见的内容和文件的实际内容不同。程序以文本模式读取文件时,把本地环境表示的行末尾或文件结尾映射为C模式。例如,C程序在旧式Macintosh中以文本模式读取文件时,把文件中的
\r
转换成\n
;以文本模式写入文件时,把\n
转换成\r
。或者,C文本模式程序在MS-DOS平台读取文件时,把\r\n
转换成\n
;写入文件时,把\n
转换成\r\n
。在其他环境中编写的文本模式程序也会做类似的转换。除了以文本模式读写文本文件,还能以二进制模式读写文本文件。如果读写一个旧式MS-DOS文本文件,程序会看到文件中的`r
和\
n`字符,不会发生映射(图13.1演示了一些文本)。如果要编写旧式Mac格式、MS-DOS格式或UNIX/Linux格式的文件模式程序,应该使用二进制模式,这样程序才能确定实际的文件内容并执行相应的动作。
但是如果文件最初使用二进制编码的字符,该文件就是文本文件,其中包含文本内容;如果文件中的二进制值代表机器语言代码或数据数值或图片或音乐编码,该文件就是二进制文件,其中包含二进制内容。
1.3 I/O的级别
底层I/O(low-level I/O)使用操作系统提供的基本I/O服务。标准高级I/O(standard high-level I/O)使用C库的标准包和stdio.h
头文件定义。因为无法保证所有的操作系统都使用相同的底层I/O模型,C标准只支持标准I/O包。
1.4 标准文件
C程序会自动打开3个文件,它们被称为标准输入(standard input)、标准输出(standard output)和标准错误输出(stand/ard error output)
通常情况下,标准输入为程序提供输入,它是getchar()和scanf()使用的文件。程序通常输出到标准输出,它是putchar()、puts()和printf()使用的文件。
标准错误输出提供了一个逻辑上不同的地方来发送错误消息。
2 .标准I/O
与底层I/O相比,标准I/O包除了可移植以外还有两个好处。第一,标准I/O有许多专门的函数简化了处理不同I/O的问题。例如,printf()
把不同形式的数据转换成与终端相适应的字符串输出。第二,输入和输出都是缓冲的。也就是说,一次转移一大块信息而不是一字节信息(通常至少512字节)。
//示例count.c //如何用标准I/O读取文件和统计文件中的字符数 #include "stdio.h" #include "stdlib.h" // 提供 exit()的原型 int main(int argc, char * argv []) { int ch; //读取文件时,存储每个字符的地方 //文件指针,FILE是一个定义在sdio.h中的派生类型 //文件指针并不指向实际的文件,它指向一个包含文件信息的数据对象,其中包含操作文件的I/O函数所有的缓冲区信息(下一章介绍) FILE *fp; unsigned long count = 0; //程序检查argc的值,查看是否有命令行参数,如果没有打印一条消息并退出程序。 if(argc != 2) { //argv[0]是该程序的名称 printf("Usage: %s filename\n", argv[0]); //exit()函数关闭所有打开的文件并结束程序(定义在stdlib.h头文件中),exit()函数的参数被传递给一些操作系统 //EXIT_FAILURE是一个宏,用于表明结束程序失败(定义在stdlib.h头文件中) //标准要求0和宏EXIT_SUCCESS用于表明成功结束程序(定义在stdlib.h头文件中) exit(EXIT_FAILURE); } //使用fopen()函数打开文件(声明在sstdio.h头文件中) //第一个参数是待打开文件的名称(更准确地说是一个包含该文件名的字符串地址) //第二个参数是一个字符串,指定待打开文件的模式 //程序成功打开后,fopen()函数返回文件指针 if( ( fp = fopen(argv[1],"r") ) == NULL ) { printf("Can`t open %s \n", argv[1]); exit(EXIT_FAILURE); } //打开文件成功,开始计算字符个数 //从fp指定的文件中获取一个字符 //get(fp) == EOF 表示程序已经读到文件末尾,EOF为一个特殊值 while((ch = getc(fp)) != EOF) { //putc()函数第一个参数是待写入的字符,第二个参数是文件指针 //当stdout作为putc()函数的第二个参数时: putc(ch, stdout) ~ putchar(ch) putc(ch, stdout); count++; } //计