流开
函数功能: (1) FILE *fopen(const char *,const char *type);
(2) FILE *(const char *, const char *type, FILE *fp);
(3) FILE *(int , const char *type);
头文件:stdio.h
阐明:
fopen函数用于打开特定文件;
它用于打开特定流上的特定文件。 调用时,首先关闭fp流,然后重用FILE结构指针fp来打开所表示的文件。 该函数通常用于重定向预定义的流,例如标准输入、标准输出和标准错误输出。
用于将一个流对应到一个已经打开的特定文件,表示这个文件的描述符。 只有当type定义的模式与指示文件的打开模式相同时,调用才能成功。 该函数多用于在某个流和不能用于I/O操作功能的文件之间建立关联,特别是管道文件和网络通信管道。
类型说明如下:
类型
文件类型
是否新建
是否为空
可读的
可写
读写位置
文本文件
不
不
是的
不
文件开头
r+
文本文件
不
不
是的
是的
文件开头
文本文件
是的
是的
不
是的
文件开头
瓦+
文本文件
是的
是的
是的
是的
文件开头
文本文件
不
不
不
是的
文件结尾
一个+
文本文件
是的
不
是的
是的
文件结尾
RB
二进制文件
不
不
是的
不
文件开头
r+b 或 rb+
二进制文件
不
不
是的
是的
文件开头
工作组
二进制文件
是的
是的
不
是的
文件开头
w+b 或 wb+
二进制文件
是的
是的
是的
是的
文件开头
ab
二进制文件
不
不
不
是的
文件结尾
a+b 或 ab+
二进制文件
是的
不
是的
是的
文件结尾
流关闭
函数:int(FILE *fp);
头文件:stdio.h
注:调用成功返回0,调用失败返回-1,并设置errno的值。 如果程序结束前没有进行流关闭操作,则写入的数据可能会停留在缓冲区中而没有保存到文件中,从而导致数据丢失。
缓冲类型
全缓冲区:这种类型的缓冲区需要在整个缓冲区填满后进行 I/O 操作,全缓冲区访问通常用于磁盘文件。
行缓冲区:在此模式下,标准 I/O 库在输入或输出中遇到换行符时执行 I/O 系统调用。 当流引用终端时,将使用行缓冲区。 因为标准I/O库收集的每一行的缓冲区长度是固定的,只要缓冲区被填满,即使没有遇到换行符,I/O系统调用也会被执行。 默认行缓冲区大小为 128 字节。
无缓冲区:标准 I/O 库不缓存字符。 如果使用标准 I/O 函数将一些字符写入没有缓冲区的流中,则相当于使用 write 系统调用函数将这些字符写入关联的打开文件中。 标准错误流通常不被缓冲,以便可以尽快显示错误消息。
设置缓冲区属性
函数:int(FILE *fp, char *buf);
int(FILE *fp, char *buf, 大小);
整数(文件*buf);
int (FILE *fp, char *buf, int 模式, 大小);
头文件:stdio.h
阐明:
该函数用于设置缓冲区为全缓冲或无缓冲,buf是指向缓冲区的指针。 当buf指向真实的缓冲区地址时,缓冲区被设置为满缓冲区,并且大小由常量指定。 当buf为NULL时,设置为无缓冲区。 该功能通常用作激活或禁用缓冲区的开关。
功能与 类似,不同的是程序员可以设置缓冲区大小大小。
用于将缓冲区设置为行缓冲区。
mode参数可以指定缓冲类型,即:(全缓冲类型)、(行缓冲类型)、(无缓冲类型)。
一般来说,在打开流但不进行其他操作时需要设置其类型,因为改变缓冲区类型会影响指向的操作参数。
缓冲区空
函数:int(FILE *fp);
头文件:stdio.h
说明:用于将缓冲区中尚未写入文件的数据强制保存到文件中。
读取功能
函数:fread(void *ptr, size, nmemb, FILE *fp);
头文件:stdio.h
说明:ptr是存放要读取的数据的缓冲区,size是读取记录的大小,nmemb是要读取的记录数,fp是要读取的流的FILE指针,其返回值是实际读取的记录数。
写函数
函数:(const void *ptr, size, nmemb, FILE *fb);
头文件:stdio.h
说明:ptr是指向存储输入数据的缓冲区的指针,size是要写入的记录的大小,nmemb是要写入的记录数,fp是要写入的流的FILE指针,返回值是实际写入的记录数。
文件结尾检查
函数: (1)int feof(FILE *fp); (2)(文件*fp);
头文件:stdio.h
说明:feof函数用于检测文件末尾是否已被读取。 当没有访问文件末尾时,返回值为0。当访问文件末尾时,返回值为1。只有在执行读操作时,才会操作文件结束标志。 该函数用于检测是否存在读或写错误。 当正常接收访问时,该函数的返回值为0。当访问异常结束时,返回值为非零,并设置errno的值。 此时errno的值是发生错误时由读写函数本身设置的。
功能
函数:void (FILE *fp);
头文件:stdio.h
说明:该函数当文件读取超出文件末尾或读写错误时,重置结束标志和错误标志。
功能
函数:int(FILE*);
头文件:stdio.h
说明:将文件指针重新指向流的开头
功能
函数:int(FILE*);
头文件:stdio.h
描述:获取当前文件的句柄
输入输出格式 输出格式
功能:
(1) int(const *,...);
(2) int (FILE *fp,const char *,…);
(3) int(char *str, const char *,...);
(4) int (char *str, 大小, const ,…);
(5)int(const*,ap);
(6) int (FILE *fp, const char *, ap);
(7) int(char *str, const char *, ap);
(8) int(char *str, size, const, ap);
头文件:stdio.h
描述: 稍微
格式化输入
功能:
(1) int scanf(const char *,...);
(2) int (FILE *fp,const char *,…);
(3) int(char *str, const char *,...);
(4) int(const char *, ap);
(5) int (FILE *fp, const char *, ap);
(6) int(char *str, const char *, ap);
头文件:stdio.h
描述: 稍微
基于字符的输出
功能:
(1)int fputc(int c,FILE *fp);
(2)int putc(int c,FILE *fp);
(3)int(int c);
头文件:stdio.h
说明:参数c表示要输出的字符;
功能
函数:int(int c,FILE *fp);
头文件:stdio.h
描述:用于将读取的字符推回到流中。
基于字符的输入
功能:
(4)int fgetc(FILE *fp);
(5)int getc(FILE *fp);
(6)int(无效);
头文件:stdio.h
说明:fgetc 和 getc 的区别在于 getc 的参数是表达式,不能有副作用,而 fgetc 可以。 getc比调用fgetc消耗的时间少; 它相当于以stdin为参数的getc函数。
基于行的输出
函数:(1)int fputs(const char *str, FILE *fp);
(2)int put(const char *str);
头文件:stdio.h
描述: 稍微
基于行的输入
函数: (1) char *fgets(char *str,int size, FILE *fp);
(2) char *gets(char *str);
头文件:stdio.h
描述: 稍微
临时文件
临时文件是指在程序运行过程中存在并使用的文件,在程序运行结束后被删除。 对临时文件的操作都是基于流进行的。
函数:(1)char *(char *str);
(2) char *(const char *, const char *);
(3) 文件*(无效);
头文件:stdio.h
阐明:
作用是生成一个有效的文件名,该文件名与任何现有的文件名不同,str指向用于保存新生成的文件名的缓冲区。 缓冲区的长度必须大于或等于stdio库中定义的常量。 调用成功返回缓冲区指针。 如果参数为NULL,则生成的文件名将存储在静态缓冲区中,但当再次调用该函数时,该区域中的文件名将被更改。 因此,如果要保存文件名,就必须开辟相应的缓冲区来存储文件名。 调用失败时返回空指针。 另外,调用次数是有限的,必须小于或等于stdio库中定义的值。 生成的文件名不能指定文件的路径和前缀,通常位于/tmp或/var/tmp目录下。
该函数与 的区别在于它可以指定临时文件所在的目录。 您可以指定文件的路径名。 路径名的选择一般如下:如果已经定义了环境变量,则使用它。 如果未定义且不为空,则路径名将是指向的缓冲区。 如果没有定义,则为NULL,是一个路径名,由stdio定义,其优先级如下:
TMP>>
指定文件的前缀,不为NULL时,由它指向的缓冲区中存储的字符串指定的前缀。 生成的文件名被放置在由该函数调用分配的动态存储区域中,并且存储文件名的缓冲区指针位于函数返回的西边。 文件使用完毕后,需要调用free来释放。
它用于打开临时文件。 该函数会创建一个临时的二进制文件,程序结束后会自动删除该文件。 当调用生成临时文件时,会先调用生成临时文件的文件名的函数,然后创建这个文件。 程序结束时,系统调用ulink函数,文件将被删除
1. 流和缓冲区
流I/O是由C语言的标准函数提供的,这些I/O可以替代系统中提供的读写函数。 事实上,流I/O内部封装了这两个基本的文件读写系统调用。 使用流I/O更方便一些,效率上没有特别大的差异。
基于流的操作最终都会调用read或write函数进行操作。 为了最大限度地提高程序的运行效率,流对象通常会提供缓冲区,以减少对系统I/O库函数的调用次数。
基于流的 I/O 提供以下两种类型的缓冲:
1. 满缓冲:直到缓冲区满时才会调用系统I/O函数。 对于读操作,进行I/O操作,直到读取内容的字节数等于缓冲区大小或者到达文件末尾,将外存文件的内容读入缓冲区; 对于写操作,执行实际的I/O操作,直到缓冲区满,并将缓冲区的内容写入外部存储文件。 磁盘文件通常是完全缓冲的。
2.行缓冲:直到遇到换行符\n才调用系统I/O函数。 对于读操作,只有遇到换行符\n时才进行I/O操作,将读到的内容写入缓冲区; 对于写操作,只有遇到换行符\n时才进行I/O操作,将缓冲区内容写入外部存储器。 由于缓冲区大小有限,即使缓冲区满时没有遇到\n,也会执行实际的I/O操作。 默认情况下,标准输入 stdin 和标准输出都是行缓冲的。
3. 无缓冲:无缓冲,数据将立即读入或输出到外部存储文件和设备。 标准错误是无缓冲的,这也可以保证错误提示和输出能够及时反馈给用户,以便用户排除错误。
2. 基于文件流的操作
常用功能:
1. 打开和关闭流
#
FILE*fopen(const char * ,const char* 类型);
文件*(int, const char*类型);
fopen函数的第一个参数表示要打开的文件的路径,第二个参数表示打开方式。
该函数用于在已打开的文件上建立流。 第一个参数是打开文件的文件描述符,第二个参数与fopen函数的第二个参数相同。 唯一的区别是,由于文件已经被打开,所以该函数不会创建新文件,也不会将文件截断为0。这一点不用注意,这两点在文件描述符打开时就已经完成了。
在Linux中,有一个函数用于关闭文件流。 函数原型如下:
#
int (文件 *fp);
如果执行成功,函数返回0,如果失败则返回EOF。 该值在stdio.h中定义,其值为-1。 当函数关闭文件时,函数会将内存中保存的文件内容写回磁盘,以后不会写回磁盘。 重要的是要理解,如果不调用函数,则必须等待内存缓冲区填满并且系统将其内容写回磁盘。 很多程序员都被一个函数是否需要检查返回值的问题所困扰。 虽然严格来说,应该检查所有系统调用的返回值并进行错误处理,但该函数出错的概率很小,几乎为0。但如果在网络环境中关闭远程文件,该函数可能会出错。 由于该函数在文件关闭时将缓冲区的内容写回到磁盘,因此该函数实际上执行的是写操作。 在网络环境中,文件的内容要通过网络传输到目的主机并写入磁盘。 在这个传输过程中,如果网络链接出现问题或者传输的数据出现错误,就会导致文件内容无法写入。 这时,该功能就会失效。 可见,如果在本地关闭文件,则不需要检查返回值; 如果在网络环境中关闭文件,则需要检查函数的返回值。
三、以字符为单位读写数据
一次读写一个字符数据的I/O方法称为一次一个字符I/O。 Linux下使用fgetc函数获取一个字符,其函数原型如下:
#
int fgetc(FILE*fp);
如果函数执行成功,则返回字符的ASCLL值,如果失败,则返回EOF。
在Linux环境下,使用fputc函数输出一个字符数据。 函数原型如下:
#
int fputc(int c, FILE*fp)
第一个参数表示要输出的字符的ASCLL值(源),第二个参数表示要输出的文件流(目标)。
4. 以行为为单位读写数据
当输入内容遇到\n时,将流中\n之前的内容发送到缓冲区的I/O方法称为每行I/O。 Linux 使用以下函数提供一次读取一行的能力。
#
char*fgets(char * buf, int n, FILE* fp);
char*获取(char*);
fgets函数的第一个参数表示存放读入的缓冲区,第二个参数n表示要读入的字符数。该参数的最大值不能超过缓冲区的长度。 fgets 函数读取直到遇到 \n 为止。 如果n-1个字符内没有遇到换行符,则只读取n-1个字符。 最后一个字符用于存储字符串结束标志\0。 需要注意的是,fgets函数也会将'\n'换行符读入缓冲区,所以缓冲区的实际有效内容应该是缓冲区中的实际字节数(不包括'\0')减1。fgets函数的第三个参数是要读取的流对象。
fgets函数的返回值有以下两种情况: 1.成功读取一行,返回缓冲区首地址。 2. 如果读取错误或文件已到达末尾,则返回 NULL。
gets 函数与 fgets 函数类似。 该函数从标准输入流中读取一行并将其存储在缓冲区中,并且不会将 '\n' 读入缓冲区。 gets函数的返回值与fgets相同。
在Linux环境下,使用fputs函数和puts函数输出一行字符串。 函数原型如下:
#
int fputs(const char* str, FILE * fp);
int put(const char*str);
fputs函数第一个参数表示存放输出内容的缓冲区,第二个参数表示要输出的文件。 执行成功则返回输出字节数,失败则返回-1。 put 函数用于将一行字符串输出到标准输出。 其参数与fputs函数的第一个参数相同。 如果输出成功,则返回输出字节数,如果失败,则返回-1。 值得注意的是,虽然gets函数读不到\n,但是puts函数却输出\n。 fputs 和 put 函数都不会输出字符串的结束字符“\0”。 对于I/O,fputs函数和fgets函数的搭配安全可靠。
五、gets函数的漏洞
gets函数和fgets函数最大的区别在于,虽然gets函数的缓冲区是由用户提供的,但用户无法指定一次可以读取多少字节。这使得gets函数成为一个危险的函数