1、C提供两种文件模式:文本模式和二进制模式
所有文件的内容都以二进制形式(0或1)存储。
文本文件(其中包含文本内容):文件使用二进制编码(例如ASCII或Unicode)的字符表示文本(比如以C字符串为内容的文件就是文本文件)。
二进制文件(其中包含二进制内容):文件中的二进制值代表机器语言代码或数值数据或图片或音乐编码。
2、C中文件指针的概念:
文件指针的类型是指向FILE的指针,FILE是一个定义在stdio.h头文件中的派生类型,文件指针并不指向实际的文件,它指向一个包含文件信息的数据对象(该数据对象是一个C结构),其中包含操作文件的I/O函数所用的缓冲区信息。因为标准I/O库中的I/O函数使用缓冲区,所以它们不仅要知道缓冲区的位置,还要知道缓冲区被填充的程度以及操作哪一个文件。标准I/O函数根据这些信息在必要时决定再次填充或清空缓冲区。(黄色突出显示文字(标记文本)后面的内容具体详情见4.2、标准I/O的机理)
3、标准文件分为:①:标准输入 ②:标准输出 ③:标准错误输出
标准文件 | 文件指针 | 通常使用的设备 |
---|---|---|
标准输入 | stdin | 键盘 |
标准输出 | stdout | 显示器 |
标准错误输出 | stderr | 显示器 |
4、I/O的级别:
底层I/O(使用操作系统提供的基本I/O服务)。
标准高级I/O(使用C库的标准包和stdio.h头文件定义)。
因为无法保证所有的操作系统共用一套底层I/O模型,C标准只支持标准I/O包,我们只讨论标准I/O。
4.1、标准I/O:
文件I/O
文件I/O函数要用FILE指针指定待处理的文件。
4.1.1、getc( )函数和putc( )函数:
getc( )和putc( )函数与getchar( )和putchar( )函数类似。(实际上putchar( )函数一般通过putc( )来定义。与此类似,getchar( )函数也通过使用标准输入的getc( )函数来定义。)
所不同的是,要告诉getc( )或putc( )函数使用哪一个文件。
下面这条语句的意思是“从标准输入中读取一个字符”:
ch = getchar( ); -----①
getc( )函数:(参数列表只有一个参数,为一个文件指针)
ch =getc(fp);--------②
语句②表示从fp(文件指针)指定的文件中获取一个字符。
所以语句①和这条语句(ch = getc(stdin);)一个效果。
putc()函数:(参数列表第一个参数是待写入的字符,第二个参数是文件指针)
下面这条语句
putc(ch,fpout);------③
表示把字符ch放进FILE指针fpout指定的文件中。
所以我们也可以想到putc(ch,stdout);和putchar(ch);这两条语句一个效果
(通过改变其中的文件指针参数,可以做比getchar( )和putchar( )函数更多的事情)
4.1.2、fopen( )函数:
该函数声明在stdio.h头文件中
参数列表第一个参数是待打开的文件名称,更确切地说是一个包含该文件名的字符串地址。
参数列表第二个参数是一个字符串,指定待打开文件的模式。
程序打开文件之后,fopen( )将会返回文件指针(file pointer),其它I/O函数可以使用这个指针指定该文件。
4.1.3、fclose( )函数(参数列表只有一个参数,为一个文件指针)
fclose(fp)关闭文件指针fp所指定的文件,必要时刷新缓冲区,关闭的文件会自动保存哦。
对于比较正式的程序,应该检查是否成功关闭文件,如果成功关闭,fclose( )函数返回0,否则返回EOF(EOF的值为-1)
如果磁盘已满(刚开始的文件内容为0字节,后面你往文件中写入内容,之后调用fclose( )函数关闭文件(此过程会保存文件),诶,磁盘满了,我的天😂),移动磁盘被移除或出现I/O错误,都会导致调用fclose( )函数失败。
4.1.4、fprintf( )函数和fscanf( )函数
文件I/O函数fprintf( )和fscanf( )函数的工作方式与printf( )和scanf( )类似,区别在于前者需要用第一个参数指定待处理的文件,另外与putc( )函数不同的是, fprintf( )函数和fscanf( )函数(当然也包括getc( )函数)它们都把FILE指针作为第一个参数
4.1.5、fgets( )函数和fputs( )函数
我之前写的博客 C语言字符串摘要 有讲
4.2、标准I/O的机理
通常,使用标准I/O的第一步是调用fopen( )打开文件(C程序会自动打开三种标准文件,这些标准文件是 scanf, printf, putchar 等不指定文件的函数的默认使用文件)。fopen( )函数不仅打开一个文件,还创建了缓冲区(在读写模式下会创建两个缓冲区)以及一个包含文件和缓冲区数据的结构,当然当C程序打开标准文件时也会创建相应的缓冲区。 另外,fopen( )返回指向该结构的指针,以便其他函数知道如何找到该结构。假设把该指针赋给一个变量fp,我们说fopen( )函数“打开一个流”。如果以文本模式打开该文件,就获得一个文本流;如果以二进制模式打开该文件,就获得一个二进制流。
这个结构通常包含一个指定流中当前位置的文件位置指示器。除此之外,他还包含错误和文件结尾的指示器、一个指向缓冲区开始处的指针、一个文件标识符和一个计数(统计实际拷贝进缓冲区的字节数)。
我们主要考虑文件输入。通常,使用标准I/O的第二步是调用一个定义在stdio.h中的输入函数,如fscanf( )、getc( )或fgets( )。一调用这些函数,文件中的缓冲大小数据块就被拷贝到缓冲区中。缓冲区的大小因实现而异,一般是512字节或是它的倍数,如4096(8倍)或16384(32倍)(随着计算机硬盘容量的越来越大,缓冲区的大小也越来越大)。最初调用函数,除了填充缓冲区外,还要设置fp所指向的结构中的值,尤其要设置流中的当前位置和拷贝进缓冲区的字节数。通常,当前位置从字节0开始。
在初始化结构和缓冲区后,输入函数要求从缓冲区中读取数据。在它读取数据时,文件位置指示器被设置为指向刚读取字符的下一个字符。由于stdio.h系列的所有输入函数都要使用相同的缓冲区,所以调用任何一个函数都将从上一次函数停止调用的位置开始。
当输入函数发现已读完缓冲区中的所有字符时,会请求把下一个缓冲大小的数据块从文件拷贝到该缓冲区中。 以这种方式,输入函数就可以读取文件中的所有内容,直到文件结尾。函数在读取缓冲区中最后一个字符后,把结尾指示器设置为真。于是,下一次被调用的输入函数将返回EOF。
输出函数以类似的方式把数据写入缓冲区。当缓冲区被填满时,数据将被拷贝至文件中。