《c primer plus》c语言学习笔记整理(十三)-文件输入输出

第十三章 文件输入输出

1.与文件进行通信
(1)文件:c把文件看做是一系列连续的字节,每个字节都能单独被读取
(2)文本模式与二进制模式:文本模式-包含文本内容的文本文件,二进制模式-图片音乐类,
1)UNIX用同一种文件格式处理文本文件与二进制文件的内容
2)在二进制模式中,程序可以访问文件的每个字节。
3)在文本模式中,程序所见的内容和文件的实际内容不同。程序以文本模式读取文件时,把本地环境表示的行末尾或文件结尾映射成C模式。(例如MS-DOS平台读取文件,把\r\n转换为\n)。
4)在二进制模式读写文件的时候,不会发生相应的映射。
(3)I/O的级别
1)底层I/O:使用操作系统提供的基本I/O服务;
2)标准高级I/O:使用C库的标准包和stdio.h头文件定义(因为无法保证所有的操作系统使用相同的底层I/O模型)
(4)标准文件(C程序自动打开三个文件)
1)标准输入:系统的普通输入设备(默认情况下,通常为键盘,)
2)标准输出:同3)一样是系统的普通输出设备,通常为显示屏。
3)标准错误输出 :提供了一个逻辑上不同的地方来发送错误消息(2)与3)为系统的普通输出设备,通常为显示屏)
注:如果使用重定向把输出发送给文件而不是屏幕,那么发送至标准错误输出的内容仍然会被发送到屏幕上。
2.标准I/O
好处:一是可移植,二是标准I/O有许多专门函数简化了处理不同I/O的问题,三是输入输出都是缓冲的。(一次转移一大块信息而不是一个字节信息(常至少512字节),缓冲区提高了数据传输效率,程序可以检查缓冲区的字节,缓冲在后台处理)。
(1)检查命令行参数
1)一些操作系统可能不识别argv[0],所以这种用法并非完全可移植。
2)exit()函数关闭所有打开的文件并结束程序。其参数被传递给一些操作系统,供其他程序使用,一般惯例为(正常结束的程序传递0,异常结束的程序传递非零值,不同的退出值可用于区分程序失败的不同原因)
3)标准要求0或宏EXIT_SUCCESS用于表明成功返回程序;EXIT_FAILURE用于表明结束程序失败。这些宏和exit()原型都位于stdlib.h头文件中。
4)在最初的调用main()中使用return与调用exit()效果相同,如果main()在一个递归程序中,exit()直接终止程序,return把控制权交给上一级递归,直至最初一级,另一个区别是,即使在其他函数中(除main()以外)调用exit()也能结束整个程序。
(2)fopen()函数
1)该函数声音在stdio.h中,第一个参数为待打开文件的名称,其实是一个包含该文件名的字符串地址,第二个参数为一个字符串,指定待打开文件的模式
2)新的C11增加了带x字母的写模式,如果以传统写模式打开一个现有文件,fopen()会把该文件长度截为0,这样就丢失了该文件的内容。带x字母的写模式,即使fopen()操作失败,原文件的内容也不会被删除。使用带x字母的任何一种形式,将无法打开一个现有文件。
3)如果环境允许,x的独占模式使得其他程序或线程无法访问正在被打开的文件。
4)程序成功打开后,fopen返回文件指针,其他I/O函数可以使用这个指针指定该文件。
5)文件指针的类型,是指向FILE的指针,这是一个定义在stdio.h中的派生类型
6)文件指针并不指向实际的文件,指向一个包含文件信息的数据对象,其中包含操作文件的I/O函数所用的缓冲区信息
7)因为标准库的I/O函数使用缓冲区,所以他们不仅要知道缓冲区的位置,还要知道缓冲区被填充程度以及操作哪一个文件。相关函数根据这些信息在必要时决定再次填充或清空缓冲区。fp指向的数据对象包含了这些信息(结构体)
(3)getc()与putc()函数:用于文件,字符获取及输出
1)putc()函数有两个参数,第一个参数为待写入的字符,第二个参数为文件指针,
2)putchar(ch,stdout)左右和putchar(ch)相同,stdout为与标准输出相关联的文件指针,定义在stdio。h中
3)putchar()函数一般通过putc()来定义,getchar()函数同理
(4)文件结尾
1)为了避免读到空文件,应该使用入口条件循环(不是do while)进行文件输入,程序应该在进入循环体之前先尝试读取。
2)
(5)fclose()函数
1)关闭fp指定的文件,必要时刷新缓冲区
2)对于较正式的程序,应当检查是否成功关闭文件
3)如果成功关闭文件,函数返回0,否则返回EOF
4)磁盘已满、移动硬盘被移除或者出现I/O错误,都会导致函数失败
(6)指向标准文件的指针
1)标准输入:stdin-键盘(常用设备)
2)标准输出:stdout-显示器
3)标准错误:stderr-显示器
注:这些文件指针都是指向FILE的指针,所以他们可以用作标准I/O函数的参数
3.文件I/O:fprintf()、fscanf()、fgets()和fputs()
(1)fprintf()和fscanf()函数:需要用第一个参数指定待处理的文件,其他和printf及scanf相同
(2)fgets()和fputs()函数
1)fgets():第一个参数与gets()函数一样,表示储存输入位置的地址(char *类型);第2个参数是一个整数,表示待输入字符串的大小;最后一个参数是文件指针,指定待读取的文件。fgets(buf, STLEN, fp)
2)fgets()函数读取输入直到第一个换行符的后面,或者读到文件结尾,或者读取STLEN-1个字符.然后在末尾添加一个空字符使之成为一个字符串,字符串的大小是其字符数加上一个空字符。如果fgets()在读到字符上限之前已读完一整行,他会把表示行结尾的换行符放在空字符前面。该函数在遇到EOF将返回NULL值,可以利用这一机制检查是否到达文件结尾;如果未遇到EOF则之前返回传给它的地址。
3)fputs()函数结束两个参数,第一个是字符串的地址,第二个是文件指针,该函数根据传入的地址找到的字符串写入指定的文件中,在打印时不会在其末尾添加换行符
4.随机访问:fseek()和ftell()
在打开的文件中直接移动到任意字节处
(1)fseek()与ftell()工作原理
1)fseek()相关参数:第一个参数-FILE指针,指向待查找的文件,第二个参数-偏移量,表示从起始点开始要移动的距离,必须是一个long类型的值(正(前移),负(后移),0(保持不动))
2)偏移量的起始点:SEEK_SET-文件开始处;SEEK_CUR-当前位置;SEEK_END-文件末尾。
3)如果一切正常,fseek返回值为0;错误(比如试图移动的距离超出文件范围)返回值为-1
4)ftell()函数的返回类型是long,返回的是当前位置。ANSI C把它定义在stdio.h中,在最初的实现的UNIX中,ftell()通过返回距文件开始处的字节数来确定文件的位置,ANSI C规定,该定义适用于以二进制模式打开的文件,以文件模式打开文件的情况不同。
(2)二进制模式与文本模式
1)许多MS-DOS编辑器都利用CTRL+Z标记文本文件的结尾,以文本模式打开这样的文件时,c能识别这个作为文件结尾的标识符,但是,以二进制模式打开相同的文件,CTRL+Z字符被看做是文件中的一个字符,而实际的文件结尾符在该字符的后面。
2)MS-DOS用\r\n组合表示文本文件换行。以文本模式打开相同的文件时,C程序把\r\n看做是\n.但是,以二进制模式打开该文件时,程序能看见这两个字符。
3)ANSI C规定,对于文本模式,ftell()返回的值可以作为fseek()的第二个参数。对于MS-DOS,ftell()返回的值把\r\n当做一个字节计数。
(3)可移植性
在文本模式中,只有以下调用可以保证其行为,定位到文件开始位置、保持当前位置不动、定位至文件结尾、到距文件开始处X的位置,而x为ftell()的返回值。
(4)fgetpos()与fsetpos()函数
1)用途:处理较大文件的新定位函数:fgetpos()和fsetpos()
2)不用long类型的值表示位置,使用一种新类型:fpos_t(代表file position type,文件定位类型)。该类型不是基本类型,根据其他类型定义。该类型的变量和数据对象可以在文件中指定一个位置,它不能是数组 类型,没有其他限制。实现可以提供一个满足特殊平台需求的类型,该类型可以实现为结构。
3)fgetpos()函数原型:

int fgetpos (FILE * restrict stream, fpos t  restrict pos);

调用该函数时,将fpos_t类型的值放在pos指向的位置上,该值描述了文件中的一个位置。如果成功,该函数返回0;如果失败,返回非0
4)fsetpos()函数原型:

int fsetpos (FILE *stream, const fpos t *pos);

调用函数时,使用pos指向位置上的fpos_t类型值来设置文件指针指向该值指定的位置。如果成功,fsetpos()函数返回0,如果失败,返回非0。fpos_t类型的值应通过之前调用fgetpos()获得。
5.标准I/O的机理
(1)输入函数:
1)第一步:调用fopen()打开文件,该函数不仅打开一个文件,还创建了一个缓冲区(读写模式下创建两个缓冲区)以及一个包含文件和缓冲区数据的结构。fopen返回一个指向该结构的指针,以便其他函数知道如何找到该结构。假设把该指针赋值给fp,我们说fopen()函数“打开一个流”,以文本模式打开该文件获得一个文本流,以二进制模式打开该文件获得一个二进制流。
2)第二步:调用一个定义在stdio.h中的输入函数,一旦调用这些函数,文件中的数据块就被拷贝到缓冲区中,缓冲区大小因实现而异,一般为512字节或是它的倍速。最初调用函数,除了填充缓冲区外,还要设置fp所指向的结构的值,尤其要设置流中的当前位置和拷贝进缓冲区的字节数。通常位置从字节0开始。
(2)输出函数
6.其他标准I/O函数
(1)int ungetc(int c,FILE *fp)函数
(2)int fflush()函数
(3)int setvbuff()函数
(4)二进制I/O:fread()和fwrite()
(5)size_t fwrite()函数
(6)size_t fread()函数
(7)int feof(FILE *fp)和int ferror(FILE *fp)函数

猜你喜欢

转载自blog.csdn.net/weixin_45096408/article/details/104758745