1、与文件进行通信
C提供了强大的通信方法,可以在程序中打开文件,然后使用特殊 的I/O函数读取文件中的信息或把信息写入文件。
1)、文件的概念
文件通常是在磁盘或固态硬盘上的一段已命名的存储区,对我们而言,stdio.h
就是一个文件名称,该文件包含一些有用的信息。
c把文件看作是一系列连续的字节,每个字节都能单独读取。
C提供两种文件模式:文本模块和二进制模式。
2)、文本模式和二进制模式
所有文件的内容都以二进制形式(0或1)储存。但是,如果文件最初使用二进制编码的字符(例如:ASCII
或Unicode
)表示文件(就像C字符串那样),该文件就是文本文件,其中包含文本内容。
如果文件中的二进制值代表机器语言代码或数值数据(使用相同的内部表示,假设,用于long
或double
类型的值)或图片或音乐编码,该文件就是二进制文件,其中包含二进制内容。
为了规范文本文件的处理,C提供两种访问文件的途径:二进制模式或文本模式。在二进制模式中,程序可以访问文件的每个字节。而在文本模式,程序所见的内容和文件的实际内容是不同。程序以文本模式读取文件时,把本地环境表示的行尾或文件结尾映射为C模式。
3)、I/O的级别
除了选择文件的模式,大多数情况下,还可以选择I/O的两个级别(即处理文件访问的两个级别)。
4)、标准文件
C程序会自动打开3个文件,它们被称为标准输入、标准输出和标准错误输出。
通常:
- 标准输入为程序提供输入,它是
getchar()
和scanf()
使用的文件。 - 程序通常输出到标准输出,它是
putchar()
、puts()
和printf()
使用的文件。 - 标准错误输出提供了一个逻辑上不同的地方来发送错误消息。
2、标准I/O
标准I/O包除了可移植以外还有两个好处:
- 标准I/O有许多专门的函数简化了处理不同I/O的问题。
如,pirntf
把不同形式的数据转换成与终端相适应的字符串输出。 - 输入和输出都是缓冲的。也就是说,一次转移一大块信息而不是一字节信息(通常至少512字节)。
注:
- 使用
exit()
函数时,要使用stdlib.h
文件。 - 如果
main()
在一个递归程序中,exit()
仍然会终止程序,但是return
只会把控制权交给上一级递归,直到最初的一级。 - 即使在其他函数中(除
main()
以外),调用exit()
也能结束整个程序。
1)、fopen()函数
该函数声明在stdio.h
中。
参数:
① 待打开文件的名称,确切的说是一个包含文件名的字符串地址。
② 一个字符串,指定待打开文件的模式。
返回值: 程序成功打开文件后,fopen()
将返回文件指针。文件指针的类型是FILE
(它是在stdio.h
文件中的派生类型)。
警告:
①如果使用任何一种“W”模式(不带x字母)打开一个现在文件,该文件的内容会被删除,以使程序在一个空白文件中开始操作,然而,如果使用带x字母的任何一种模式,将无法打开一个现有文件。
②r+和w+的区别在于,在文件不存在时,r+不会创建文件,而w+会创建文件。
2)、getc()和putc()函数
①getc函数
用法:ch=getc(fp)
含义:从fp指定的文件中获取一个字符并赋值给变量ch. 此处fp是FILE类型的指针。
②putc函数
用法:putc(ch,fpout)
含义:把字符ch放入FILE指针fpout指定的文件中。
参数:
①待写入的字符,
②目标文件指针。
另外《putc(ch,stdout) <==> putchar(ch)
》
3)、文件结尾
从文件中读取数据的程序在读到文件结尾要停止。如果getc()
函数在读取一个字符时发现是文件结尾,它将返回一个特殊值EOF
。
4)、fclose()函数
函数原型:
fclose(fp)
函数关闭fp指向的文件,必要时刷新缓冲区。如果成功关闭,该函数返回0,否则返回 EOF
。
5)、指向标准文件的指针
stdio.h
头文件把3个文件指针与3个标准文件相关联,C程序会自动打开这3个标准文件。
标准文件 文件指针 通常使用的设备
3、文件I/O
1)、fprintf()函数和fscanf()函数
它们与prinft()
和scanf()
类似,区别在于它们需要用第1个参数指定待处理的文件。
① fscanf()
函数
用法:fscanf (stdin,”%40s”,words)
含义,从标准输入中拿把长度在40以内的字符串并赋值给words
.
返回值:返回成功读取到的元素的数量。
注: feof(fp)
找到文件的结束符,则返回1,反之则返回0;
② fprintf()
函数
功能:将内存中的数据,写入fp所代表的文件中。
用法一:fprintf (fp,”%s\n”,words)
含义,把字符串指针words所指向的字符输出到fp所指向的文件中。
用法二:fprintf (stderr,”Error closing file\n”)
含义,把字符串输出到标准错误所指向的文件中。
用法三:fprintf (stdout,”Can’t open file\n”)
含义,把字符串输出到标准错误所指向的文件中。
rewind(fp);
/返回到文件开始处/
2)、fgets()和fputs()函数
①fgets()
函数
功能: 从目标文件中以字符串的形式读取,一次性读取size个字节
参数:
①储存输入位置的地址(char *
类型);
②为一个整数,表示待输入字符串的大小,
③目标文件指针。
返回值:成功读取返回字符串,失败返回NULL
它是以行读取,如果大小比一行长,则把整行读取出来,并不会读取下一行。每次读取时,会进行数据覆盖,要进行拼接需要手动偏移地址。,
用法:
函数读取输入直到第1个换行符的后面,或读到文件结尾,或者读取到size-1个字符,然后在末尾添加一个空字字符使之成为一个字符串。
②fputs ()
函数
功能: 将s字符数组的内容写到fp指定的文件中。
参数:
①待输出字符串的地址(char *类型);
②目标文件指针。
示例: fputs(buf,fp)
;buf是字符串的地址,fp用于指定目标文件。
注,由于fgets()
保留了换行符,fputs()
就不会再添加换行符。
3)、随机访问:fseek()和ftell()
1、fseek()
函数
功能:在fopen
打开的文件中直接移动到任意字节处。
参数:
①FILE指针,指向待查找的文件;
②偏移量,该参数表示从起始点要移动的距离(该参数是long类型的值),可以为正(前移)、负(后移)或0(不动);
③确定起点(SEEK_SET:文件开始处,SEEK_CUR:当前位置,SEEK_END:文件末尾)。
返回值: 正常返回0,出现错误返回-1.
用法:fseek(fp,0L,SEEK_END);
/定位到文件末尾(从文件末尾偏移0)/
2、ftell()
函数
功能:返回一个long类型的值,表示文件中的当前位置(即指向文件的当前位置距文件开始处的字节数。)。
用法: ftell(fp);
/获取当前位置距文件开关的字节数/
另外,由于以上两个定位函数指导文件大小 限制在long类型能表的范围内,因此有新的fgetpos()
和fsetpos()
函数可以替换。
fgetpos()
函数原型:int fgetpos(FILE * restrict stream,fpos_t * restrict pos),
其中pos描述了文件中的当前位置距文件开头的字节数。
fsetpos()
函数原型:int fsetpos (FILE * restrict stream,const fpos_t * restrict pos),
其中pos描述了要指向的文件位置。
4、标准I/O的机理
通常,使用标准I/O的第1步是调用fopen()打开文件(此时,C程序会自动打开3种标准文件)。fopen()函数不仅打开一个文件,还创建了一个缓冲区(在读写模式下会创建两个缓冲区)以及一个包含文件和缓冲数据的结构。
通常,使用标准I/O的第2步是调用一个定义在stdio.h
中的输入函数,如fscanf()
、getc()
或fgets()
。一调用这些函数,文件中的缓冲大小数据块就被拷贝到缓冲区中。缓冲区的大小因实现而异,一般是512字节或是它的倍数。
5、其它标准I/O函数
1) ungetc
函数
功能: 把C指定的字符放回输入流中。
2)ffluch()
函数
功能: 引起输出缓冲区所有的未写入数据被发送到fp指定的输出文件,这一过程称为刷新缓冲区,如果fp是空指针,所有输出缓冲区都被刷新。
3)setvbuf()
函数![在这里插入图片描述](https://img-blog.csdnimg.cn/604452da2eb143348419f8bec1941fde.png)
功能: 创建一个代标准I/O函数替换使用的缓冲区。
在打开文件后且未对流进行其他操作之间,调用该函数
参数:
①识别待处理的流,
②指向待使用的存储区,
③为_IOFBF完全缓冲(在缓冲区满时刷新)或__IOLBF行缓冲(在缓冲区满时或写入一个换行符时)或__IONBF(无缓冲),
④对象大小。
用法: 假如程序要储存一种数据对象,每个数据对象的大小是3000字节,可以使用该函数创建一个缓冲区,其大小 是该数据对象大小的倍数。
示例: setvbuf(fa,NULL, _IOFBF,BUFSIZE)
(其中BUFSIZE已在程序中用宏进行大小定义)
4)二进制I/O:fread()
和fwrite()
一般而言,fprintf()
把数值转换为字符数据,这种转换可能会改变值。为保证数值在储存前后琶,最精确的做法是使用与计算机相同的位组合来储存。如果以程序所用的表示法把数据储存在文件中,则称以二进制形式储存数据。不存在数值形式到字符串的转换过程。用数据表示机器语言指令的文件都是二进制文件。
①fwrite()
函数
功能: 把二进制数据写入文件。
参数:
①为待写入数据块的地址,
②数据块的大小(一般是sizeof运算符的返回值),
③数量,
④待写入的目标文件的指针。
示例: char buf[256]; fwrite(buf,256,1,fp)
释义:调用一块256字节的数据从buf写入文件。
返回值: 返回成功写入项的数量。正常情况下,该返回值就是nmemb,但如果写入错误,返回值会比nmemb小。
②fread()
函数
功能: 用于读取被fwrite写入文件的数据。。
参数:
①为待读取数据在内存的地址,
②为数据块的大小(一般是sizeof运算符的返回值),
③是数量,
④待读取的目标文件的指针。
示例: double earn[10]; freadd(earn,sizeof(double),10,fp)
释义:把10个double大小的值拷贝进earn数组中。
返回值: 返回成功读取项的数量。正常情况下,该返回值就是nmemb,但如果读取错误或读取文件结尾,返回值会比nmemb小。
5)int feof(FILE *fp)
和int ferror(FILE *fp)
如果标准输入函数返回EOF,则通常表明函数已经到达文件结尾。然而,出现读取错误时,函数也会返回EOF。当上一次输入调用检测到文件结尾时,feof()
函数返回一个非零值,否则返回0.当读或写出现错误,ferror()
函数会返回一个非零值,否则返回0。