Linux操作系统应用软件编程——标准IO
文件操作:一切皆文件
文件类型
Linux系统下所有文件均属于以下七种类型
1)b,块设备文件(存储类设备,例如硬盘)
2)c,字符设备文件(包括但不限于输入输出设备,例如鼠标键盘显示器)
3)d,目录文件(文件夹)
4)-,普通文件(包括但不限于xxx.c,xxx.h,xxx.txt,xxx.jpg,a.out)
文本文件:1.txt,xxx.c
二进制文件:xx.jpg,a.out
可以打开该文件来区分,若是乱码则是二进制文件
5)l,软链接文件(快捷方式)
6)s,套接字文件(用于网络通信)
7)p,管道文件(用于进程间通信)
例:用ls -l密令可以把当前文件的详细信息显示出来,作用等价于ll密令,以第一个文件为例
第一个字符‘d’,表示该文件属于什么文件类型,为目录文件。
三个rwx为文件操作权限,其中r(read)为读取权限,w(write)为写权限,x为可执行权限,-为无权限。第一组rwx为自己对文件的读写执行权限,第二组r-x为同组用户对文件的读写权限,剩下的是其他人对文件的读写权限。
数字为37为链接个数
两个linux分别表示用户名和组名,第一个进入组的成员名就是组名
数字4096为文件大小
日期为文件最后被修改的时间
最后为文件名称(.为本文件,..为上一文件)
文件操作思想
打开文件---->读写文件---->关闭文件
在Linux操作系统中,默认打开三个文件
FILE* stdin:标准输入流,对应于标准输入设备:键盘
FILE* stdout:标准输出流,对应于标准输出设备:显示屏
FILE* stderr:标准出错流,对应于标准出错设备:显示屏
文件操作方法
标准IO和文件IO,其中I表示input,O表示output,即输入输出,所以IO表示的是对文件的操作
标准IO
C库提供的一套对文件操作的操作方法,即库函数,位于man手册第三章节(第一章节和第二章节分别为Linux密令和系统调用)
标准IO属于C库函数,移植性强,是系统调用的一次封装,增加了缓冲区,目的是提高数据读写效率,主要用在对配普通文件的操作上,且操作方法比较多
打开文件:fopen
读/写文件:fgets/fputs(一个字符),fgets/fputs(一行数据),fread/fwrite(固定大小的二进制数据,例如结构体)
关闭文件:fclose
文件IO
Linux内核提供的一套对文件操作的操作方式,即系统调用。必须基于Linux系统上,Windows操作系统上没有。
属于系统调用,只能用于Linux操作系统,移植性弱,无缓冲区,主要应用在对硬件操作的,也可以操作普通文件
缓冲区
1,行缓冲1k(1024字节),用于人机交互界面、终端
缓冲区刷新方法:
1)程序结束自动刷新
2)遇到\n刷新
3)fflush()函数强制刷新
4)缓冲区满自动刷新
2,全缓冲4k(4096字节),用于文件缓冲区
缓冲区刷新方法:
1)程序结束自动刷新
2)fflush()函数强制刷新
3)文件关闭刷新
4)缓冲区满自动刷新
3,无缓冲0k,用于出错信息对应设备
缓冲区刷新方法:stderr无缓冲
标准IO
fopen
功能:打开一个文件,这个文件的名字为被pathname指向的字符串,并返回一个文件流指针
文件流:数据从文件流入流出体现出来的字节流,用FILE表示,而FILE *为文件流指针,对应到了一个已打开的文件
形参:
pathname:打开的文件名地址
mode:打开的方式,打开方式如下
返回值:成功则会返回文件流指针,失败则返回NULL
虽然fopen是打开文件,但是并不会跳出一个图形化界面
fclose
功能:关闭一个流
参数:文件流指针
fgetc、fputc
fputc
功能:向文件中只写入一个字符
参数:要写入的字符c,要写入的文件流指针
返回值:成功则为字符的ASCII码值,失败则为EOF(-1)这个宏
就会在1.txt文件中清空并输入一个A,可以用od -c加文件名的形式,以字符的形式输出到终端
向文件中输入“hello world”
fgetc
功能:从文件中读取一个字符,fgetc(stdin)等价于getchar
参数:要读取文件的文件流指针
返回值:成功则为督导的字符的ASCII码,失败或读到文件末尾都是EOF
该函数会自动向后读取,不是每次都从文件第一个字符开始读取
fgetc和fputc实现文件拷贝
主函数传参
主函数int main(int argc, const char *argv[]),其中argc为程序运行时,给主函数传参的个数,argv指针数组,指向主函数传递的参数,argv[0]指向a.out。
实参:运行程序时,a.out aaa bbb,均为实参
形参:主函数中的参数
所以文件拷贝还可以通过以下方式
不仅仅是文本文件,图片文件也可以拷贝
fgets、fputs
注意:该函数不能读写二进制文件
fputs
功能:向文件中写入字符串(不会写入'\0'字符)
参数:字符串首地址,文件流指针
返回值:成功则为非负的整型数据,失败则为EOF
fgets
功能:从文件中最多读取一行数据,换行则停止
参数:存放读取到数据的内存空间的首地址;希望读到的字节数;文件流指针
返回值:成功则为s的首地址,失败或读到文件末尾则为NULL
该函数依然有向后读取的功能,若是想要读取一整个文件的内容,可以参考fgetc的循环,终止条件是返回值为NULL
fgets和gets的区别
fgets | gets |
从指定的已打开文件中读取最多一行数据(遇到\n停止读取) | 指定从终端读设备读取数据 |
保留\n字符并在字符串末尾添加\0 | 将终端读到的\n替换成\0 |
最多读取sizeof - 1个字符,最后一个位置存放\0 | 危险,在读取时没有大小限制,可能造成数据越界 |
由于gets可能造成数组越界,所以gets函数几乎是被禁止使用的,而fgets会保留\n字符,所以在打印字符串会多打出一个换行,要解决这个问题只需要手动的将数组最后一个元素换成\0即可
fgets和fputs实现文件拷贝
由于fgets最多读取一行数据,所以需要用到循环,直到读到文件末尾,但是该函数无法完全做到复制图片,会造成数据丢失,因为图片属于二进制文件,并不会写入0,因为在文本文件中,0等价于‘0’,而在二进制文件中,0等价于‘\0’
fread、fwrite
这俩函数主要用来读写二进制文件,也可以读写文本文件
fwrite
功能:向文件中写入nmemb个大小是size的数据到文件中
参数:要写入的数据的首地址;每个元素的字节数;写入元素个数;要写入的文件流指针
返回值:成功则返回实际写入的元素个数,未说失败
fread
功能:从文件中读取nmemb个大小是size的元素
参数:存储读取到数据的内存的首地址;每个元素大小;读取元素个数;文件流指针
返回值:成功则为实际读到的元素个数,读到文件末尾则为0
fseek
功能:实现文件流重新定位
参数:需要定位的文件流指针;向后偏移量(负数则向前偏移);定位的相对位置(whence)
返回值:成功则为当前偏移量,失败则为-1
从h开始,向后偏移10个,到d的位置,输入A,然后指针自动向后移,指向A之后,输入D,文件末尾从D之后开始,向前偏移5个,到o的位置,输入B,然后指向B之后的r,输入C
ftell
功能:获取流的当前位置到文件开头的偏移量
参数:文件流
返回:偏移量字节
模拟迅雷
在第三步中,虽然可以写成fwrite(fpsrc, len, 1, fpdst)且不报错,但是这是U盘对U盘,文件的拷贝需要通过内存空间,即将文件内容放入内存空间中,在写在另一个U盘中
为了避免读取数据时访问到不该访问的区域,可以通过循环,一次一个字节,分多次访问,可以参考fgetc
rewind
功能:流复位函数,复位到开头,等价于fseek(fp, 0, SEEK_SET)
参数:文件流指针