做特价网站百度云网站建设视频教程
web/
2025/10/4 12:46:01/
文章来源:
做特价网站,百度云网站建设视频教程,桩基工程信息网发布,企业网络营销策略10.1 文件I/O操作概述在Linux系统中#xff0c;文件I/O操作可以分为两类#xff0c;一类是基于文件描述符的I/O操作#xff0c;另一类是基于数据流的I/O操作。10.1.1 文件描述符简介在文件操作一章中#xff0c;也经常提到文件描述符这个概念。所谓文件描述符#xff0c;就…10.1 文件I/O操作概述在Linux系统中文件I/O操作可以分为两类一类是基于文件描述符的I/O操作另一类是基于数据流的I/O操作。10.1.1 文件描述符简介在文件操作一章中也经常提到文件描述符这个概念。所谓文件描述符就是进程与打开的文件的一个桥梁通过这个桥梁才可以在进程中对这个文件进行读写等操作。在Linux环境下每打开一个磁盘文件都会在内核中建立一个文件表项文件表项中存储着文件的状态信息、存储文件内容的缓冲区和当前文件的读写位置。如果同一磁盘文件打开了3次就会创建3个这样的文件表项(a,b和c)读写文件时只会改变该文件表项中的文件读写位置。这3个文件表项存储在一个文件表数组table[3]中在这里table[0]a,table[1]b,table[2]c。这个文件表的下标就称之为文件描述符将这个文件描述符存储在一个数组中des[3]{0,1,2},那么在进程中就可以通过这个des数组下标引用文件表项。也就是说通过文件描述符就可以访问到这个磁盘文件。10.1.2 数据流概述从数据操作方式这个角度来说Linux系统中的文件(无论是普通文件还是设备文件)可以看做是数据流。对文件进行操作之前必须先调用标准I/O库函数fopen()将数据流打开。打开数据流之后就可以对数据流进行输入和输出的操作。标准I/O库函数是C语言中所特有的用于高级接口的函数这些库函数存放在C语言的stdio.h头文件中因此这些用于数据流的I/O操作函数不仅适用于Linux系统还适用于其他的操作系统。由此可见此库函数的引用大大增加了程序的移植性。要对数据流进行读写操作时需要标准I/O库函数和FILE类型的文件指针一起来实现。这个文件指针石达开数据流时返回的指针该指针用来表示要操作的数据流。当执行程序时有3个数据流不需要特定的函数进行打开的操作他们会自动打开。这3个数据流是标准输入、标准输出和标准错误输出。他们是自动打开的当不使用时也会自动关闭。然而调用标准I/O库函数fopen()打开的数据流在对数据流进行操作后需要调用fclose()函数将其关闭。fclose()函数在关闭数据流之前会清空在操作过程中分配的缓冲区并保存数据信息。10.2 基于文件描述符的I/O操作10.2.1 文件的打开与关闭1)open()函数#include#include#includeint open(const char *pathname, int flags)int open(const char *pathname, int flags, mode_t mode)int creat(const char *pathname, mode_t mode)上述的两个open()函数和一个creat()函数在调用成功时都会返回其新分配的文件描述符否则返值为-1并设置适当的error。2)close()函数#incldueint close(int fd)当一个进程终止时内核对该进程的所有尚未关闭的文件描述符调用close()函数关闭所以即使用户程序不调用close()函数在终止时内核也会自动关闭它打开的所有文件。但是对于网络服务器这种一直运行的程序文件描述符一定要及时关闭否则随着打开的文件越来越多会占用大量文件描述符和系统资源。有函数open()返回的文件描述符一定是该进程尚未使用的最小描述符。由于程序启动时自动打开标准输入、标准输出和标准错误输出因此文件描述符0,1,2会存在那么第一次调用open()函数打开文件时返回的文件描述符通常会是3再调用open()函数就会返回4.可以利用这一点在标准输入、标准输出或标准错误输出上打开一个新文件是想重定向的功能。例如首先调用close()函数关闭文件描述符1然后调用open()函数打开一个常规文件则一定会返回文件描述符1这是标准输出就不再是终端而是一个常规文件了再调用printf()函数就不打印到屏幕上而是写到这个文件中了。在文件操作一章中讲到的dup2()函数就是另外一种在指定的文件描述符上打开文件的方法。10.2.2 文件的读写操作1)read()函数#includessize_t read(int fd, void *buf, size_t count)2)write()函数#includessize_t write(int fd, const void *buf, size_t count)10.2.3 文件的定位每个文件都记录着当前读写位置打开文件时读写位置是0表示文件开头通常读写多少个自己就会将读写位置往后移多少个字节。以O_APPEND方式打开文件每次写操作都会在文件末尾追加数据然后间读写位置移动到新的文件末尾。1)lseek()函数lseek()函数可以移动当前读写位置通常称为偏移量该函数的定义形式如下#include#includeoff_t lseek(int fildes, off_t offset, int whence)10.3 基于数据流的I/O操作10.3.1 文件的打开与关闭在操作文件之前要用fopen()函数打开文件操作结束后要用fclose()函数关闭文件。1)fopen()函数#includeFILE *foepn(cosnt char *path, cosnt char *mode)2)fclose()函数#includeint fclose(FILE *fp)10.3.2 字符输入/输出1)fgetc()函数fgetc()函数从指定的文件中读一个字节该函数的定义形式如下#includeint fgetc(FILE *stream)在程序中偶尔会遇到getchar()函数也是用于读取一个字节但它是从标准输入读一个字节。在程序中调用getchar()函数相当于调动fgetc(stdin)在使用fgetc()函数时需要注意一下几点①调用fgetc()函数时指定的文件的打开方式必须是可读的。②函数fgetc()调用成功时返回的是读到的字节应该为unsigned char但fgetc()函数在原型中返回值类型时int原因在于函数调用出错或读到文件末尾时fgetc()会返回EOF即-1保存在int型的返回值是0xffffffff,如果读到字节0xff由unsigned char型转换int 型时0x000000ff只有规定返回值是int型才能把这种情况区分开如果规定返回值是unsigned char型那么当返回值是0xff时则无法区分到底是EOF还是字节0xff。2)fputc()函数#includeint fputc(int c, FILE *stream)10.3.3 字符串输入/输出1)fgets()函数#includechar *fgets(char *s, int size, FILE *stream)对于fgets()函数而言\n是一个特别的字符作为结束符而\0并无任何特别之处只用作普通字符串读入。正因为\0作为一个普通的字符串因此无法判断缓冲区中的\0究竟是从文件读上来的字符还是有fgets()函数自主添加的结束符所以fgets()函数只用于读文本文件而不提倡读二进制文件并且文本文件中的所有字符串不能有\0。2)fputs()#includeint fputs(const char *s, FILE *stream)缓冲区s中保存的是以\0结尾的字符串fputs()将该字符串写入文件stream但并不写入结尾的\0且字符串中可以有\n,也可以没有\n。10.3.4 数据块输入/输出1)fread()和fwrite()函数#includesize_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)10.3.5 格式化输入/输出所谓格式化输入/输出就是按照一定的格式将数据进行输入/输出操作。在程序中经常用到的printf()函数和scanf()函数是用于对终端设备文件的读写操作这两个函数被称为格式化输入/输出因为在使用这两个函数时需要制定读写数据的数据类型并按照一定的格式进行读写。1)格式化输入函数#includeint printf(const char *format,...)int fprintf(FILE *stream, const char *format)int sprintf(char *str, size_t size, const char *format,...)2)格式化输出函数#includeint scanf(const char *format,...)int fscanf(FILE *stream, const char *format,...)int sscanf(const char *str, const char *format,...)10.3.6 操作读写位置的函数1)fseek()函数#inlcudeint fseek(FILE *stream, long offset, int whence)函数fseek()的作用是用来移动文件内部位置指针。2)ftell()函数#inlcudelong ftell(FILE *stream)ftell()函数的作用是得到stream指定的流式文件中的位置。3)rewind()函数void rewind(FILE *stream)rewind()函数的作用是使位置指针重新返回文件的开头该函数没有返回值。10.3.7 C标准的I/O缓冲区C标准库在调用fopen()函数时都会给此文件分配一个I/O缓冲区可以加速读写操作原因在于用户程序需要调用C标准I/O库函数(如fread()、fwrite()等基于文件流I/O操作)读写文件当缓冲区装满后再由系统调用的I/O函数(如read()、write()等基于文件描述符的I/O操作)把读写请求传给内核最终由内核驱动磁盘或设备完成I/O操作。由此看来为文件分配的内存缓冲区大小直接影响到实际操作外村设备的次数内存中为未见分配的缓冲区越大操作外存的次数会越小因此读写数据的速度会越来越快效率就会随之增高。然而有时用户程序等不及将缓冲区都装满之后再传给内核进行I/O操作而是希望把I/O缓冲区中的数据立刻传给内核让内核写回设备这种行为叫做flush操作对应的库函数是fflush()。C标准库的I/O缓冲区有全缓冲、行缓冲和无缓冲3种类型。1)全缓冲如果缓冲区写满了就写回内核。普通文件通常是全缓冲的。2)行缓冲如果用户程序写的数据中有\n就把这一行写回内核或者缓冲区写满后就写回内核。标准输入和标准输出对应中断设备时通常是行缓冲。3)无缓冲用户程序每次调库函数做写操作都要通过系统调用写回内核。标准错误输出通常是无缓冲的。这样用户程序产生的错误信息就可以尽快输出到设备。使用缓冲区时会使用到如下两类操作一个是设置缓冲区属性另外一个是清空缓冲区。4)设置缓冲区属性#includevoid setbuf(FILE *stream, char *buf)void setbuffer(FILE *stream, char *buf, size_t size)void setlinebuf(FILE *stream)int setvbuf(FILE *stream, char *buf, int mode, size_t size)setbuf()函数主要实现了为参数buf所指定的缓冲区设置大小。此函数中设定缓冲区大小的值只有两个一个是常数BUFSIZ另一个是NULL。当定义值为BUFSIZ时代表设置缓冲区为全缓冲若为NULL则代表设置缓冲区为无缓冲形式。setbuffer()与setbuf()功能相同只是setbuffer()函数可以任意指定缓冲区大小为sizesetlinebuf()函数实现了将stream指向的缓冲区设置为行缓冲。setvbuf()函数融合了上述3种函数的功能既可以设置缓冲区的任意大小size也可以设置缓冲区的任意类型如mode参数取值为_IOFBF(全缓冲类型)、_IOLBF(行缓冲类型)或_IONBF(无缓冲类型)。5)清空缓冲区#includeint fflush(FILE *stream)fflush()函数实现将缓冲区中的尚未写入文件的数据强制性地写进stream所指定的文件中然后清空缓冲区。如果stream为NULL此函数会将所有打开的文件数据更新。10.4 小结本章主要介绍了Linux系统下的文件I/O操作。在Linux系统下存在两种文件I/O操作一种是基于文件描述符的I/O操作这里面的I/O操作都是Linux系统中提供并直接作用于内核的是非缓冲的I/O操作另一种I/O操作是基于数据流的I/O操作是由C语言的stdio库所提供的需要在内存中开辟一块缓冲区在缓冲区中进行快速地读写操作。本章主要结合典型实例介绍了上述两种I/O操作方式对文件的打开、关闭、读、写、文件定位等操作。注感觉本文10.3.5之前的内容对我有用让我大概明白了基于数据流的文件I/O和基于文件描述符的文件I/O操作之间的区别。但是如果在给出其中的从操作函数之后给出一些实例就更好了。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/86784.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!