推广 热搜: csgo  vue  angelababy  2023  gps  新车  htc  落地  app  p2p 

Linux基于流IO

   2023-07-23 网络整理佚名1990
核心提示:流I/O是由C语言的标准函数提供的,这些I/O可以替代系统中提供的read和write函数。事实上流I/O的内部封装了这两个基本的文件读写系统调用。基于流的操作最终会调用read或者write函数进行操作。基于流的I/O提供以下2种缓冲:标准输入stdin和标准输出都默认是行缓冲的。gets函数和fgets函数类似,该函数从标准输入流中读取一行并将其存入一个缓冲区,并不将‘\n’读进缓冲区中。

流开

函数功能: (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函数成为一个危险的函数

 
反对 0举报 0 收藏 0 打赏 0评论 0
 
更多>同类资讯
推荐图文
推荐资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报
Powered By DESTOON