标准IO
一、IO
IO是输入输出的意思,是对文件的输入输出操作。文件存放在磁盘中,而内存只用于进行数据的处理,不可
以用于存储文件。IO的作用用于将内存中的数据,写入磁盘中,以此将文件存放在磁盘上。
二、IO对象
1、Linux系统的文件类型:
在Linux系统下存在“一切皆文件的思想”,即把Linux中的所有内容都视作为文件。因此Linux系统下有7种
类型的文件:
1)普通文件 -
2)目录文件 d
3)链接文件 l (相当与Windows下的快捷方式)
4)块设备文件 b
5)字符设备文件 c
//说明:Linux为外围设备创建一个文件,用于操作和管理外围设备,如对于Linux系统而言,键盘、鼠标相当
于字符设备文件;sd卡、U盘相当于块设备文件。
6)管道文件(有名管道) p
7)套接字文件 s (套接字文件是用于两个进程之间进行通讯的一种通讯介质文件)
三、标准IO库
1、标准
标准IO是C语言的标准。
2、标准IO
标准IO是在库文件中存放了一组用于对文件进行输入、输出操作的函数。
3、标准IO库
标准IO库中存放了一组用于对文件进行输入输出操作的一组函数,是标准C库的一个子集。
四、文件指针:FILE*
文件指针:指向内存中已经打开的文件的一个指针,通过该文件指针可以对相关联的文件进行操作。在Linux
系统中已经打开的文件在内存中是以FILE结构体的形式存在。
五、缓冲机制
缓冲机制用于Linux的内存和硬盘之间的交互,标准IO封装了缓冲机制。缓冲机制、内存、硬盘三者之间的
关系可以理解为零售商、消费者、企业之间的关系:缓冲机制相当于零售商的关系,避免了内存与硬盘之间
频繁的系统调用。
标准IO通过缓冲机制减少系统调用,实现更高的效率。系统调用即操作系统的接口,不同的操作系统的接口
是不同的。
全缓冲:当缓冲区满、刷新缓冲区是才执行实际的IO操作
行缓冲:遇见换行符'\n'、缓冲区满、缓冲区刷新时才执行实际的IO操作
不缓冲:例如标准出错是不缓冲
fflush()函数:
函数原型:int fflush(FILE *stream);
功能:强制刷新文件指针所指向的内容
setbuf()函数:
函数原型:void setbuf(FILE *stream, char *buf);
功能:把缓冲区与对应的流相关联
例:setbuf(stdout, NULL); 关闭标准输出设备的缓冲机制。
stderr 标准出错流指针
stdout 标准输出流指针
stdin 标准输入流指针
例题:测量行缓冲和全缓冲的缓冲区大小。
分析:FILE 结构体中的成员来测量。
#include <iostream>
using namespace std;
int main()
{
printf("Hello World");//激活输出流的缓冲机制,即激活行缓冲的缓冲机制
printf("%d ", stdout->_IO_buf_end - stdout->_IO_buf_base);
FILE *fp = open("log.txt", "w+");
fprintf(fp, "lilei");//激活全缓冲的缓冲区
printf("%d ", fp->_IO_buf_end - stdout->_IO_buf_base);
return 0;
}
六、标准IO函数
1、fopen函数
函数原型:FILE *fopen(const char *path, const char *mode);
参数:path 文件名,是一个字符串常量,可以包含文件的路径。
mode 权限,字符串类型,即文件的操作权限。
r 以只读的方式打开文件,文件必须存在
w 以只写的方式打开文件,文件不存在则创建;文件存在,则清空文件中的内容
a 以追加的方式打开文件,文件不存在则创建;文件存在,如果读文件,则从文件开头读取
;如果向文件中写入内容,则以追加的方式写入
+ r+ 读写方式(但是文件必须存在)
+ w+ 读写方式
+ a+ 读写方式
返回值:打开文件成功,返回一个指向文件的文件流指针;打开文件失败,则返回NULL。
2、fclose函数
函数原型:int fclose(FILE *stream);
参数:文件流指针
返回值:关闭文件成功,则返回0;关闭文件失败,则放回-1,并且修改错误号errno
处理错误信息
1、perror函数
函数原型:void perror(const char *s);
功能:perror函数会先输出指针s所指向的字符串,参数可有可无,起到提示作用;接着输出标准错误流中错
误号对应的错误信息。
2、strerror函数
函数原型:char *strerror(int errno);
参数:errno是错误号,全局变量。
返回值:返回错误号对应的字符串错误信息。
错误号:errno
它是一个全局变量,任何一个错误发生都会修改错误号的值,它的值是一些宏定义。
3、fread函数
函数原型:size_t fread(void *ptr, size_t size, size_t n, FILE *fp);
功能:按对象从指定文件中读取数据。从fp所指向的文件中“期望”读取n个对象存放在指针ptr所指向的缓冲区
中;其中每个对象的大小是size个字节。
返回值:成功,返回“实际”读取到的对象的个数;失败或者读取到文件的尾部返回0。
4、fwrite函数
函数原型:size_t fwrite(const char *ptr, size_t size, size_t n, FILE *fp);
函数功能:将缓冲区ptr中存放的数据写入到流指针fp所指向的文件中。每次“期望”写入n个数据对象,每个数
据对象的大小是size个字节。
返回值:写入成功,返回实际写入到文件中的对象个数;写入失败,则返回0
例题:通过标准IO实现文件的拷贝功能。
分析:读取多少,写入多少。
while((ret = fread(buf, 1, BUF_SIZE, fp_src) > 0)
fwrite(buf, 1, ret, fp_des);
5、fgets、gets函数
gets和fgets函数都是按行进行读取数据,但是fgets函数比gets函数更加安全。gets函数不会进行越界
检查,可能导致栈区的溢出。
1、gets函数
函数原型:char *gets(char *buf);
参数:存放由标准输入获取到的数据的缓冲区。
功能:从标准输入中读取一行存放在缓冲区buf中。
2、fgets函数
函数原型:char *fgets(char *buf, int size, FILE *fp);
功能:从流指针所指向的文件中期望读取“size - 1”个字节的数据存放在缓冲区buf中。
参数:buf 数组名,数据读取后存放的缓冲区位置的首地址
size 期望读取的字节数(size -1 个字节)
fp 目标文件的流指针
返回值:读取成功,返回缓冲区的首地址;读取失败,返回NULL。
说明:
1)fgets函数比get函数更加安全,它只会读取指定大小的数据。
2)fgets函数遇到'\n'或者已经输入"size - 1"个字符时返回。并且,fgets函数总是在尾部包含'\0'
例如:
char buf[6] = {'\0'};
1)输入“abcd回车”时,在buf中存放的是 :a b c d '\n' '\0'
2)输入“abcdef”时,在buf中存放的是:a b c d e '\0'
==》fgets函数最多读取size - 1个字符。
6、ftell函数
函数原型:long ftell(FILE *stream);
函数功能:获取流的当前读写位置,相当于文件开头的偏移量。
返回值:返回相对于文件开头的偏移量
7、fseek函数
函数原型:long fseek(FILE *stream, long offset, int whence);
函数功能:改变流的当前读写位置,对当前读写位置进行设置
参数:stream 函数流指针
offset 性对偏移量,可正可负
whence 相对偏移的基准点
SEEK_SET 相对偏移的基准点设置在文件的开头
SEEK_CUR 以当前文件的读写位置为相对偏移的基准点
SEEK_END 以文件的末尾为相对偏移的基准点
whence + offset ==>流的新的读写位置
返回值:成功,则返回0;失败,则放回-1
获取文件的大小:
1)将文件的读写位置设置在文件的尾部。
2)利用ftell函数来获取文件的大小
8、rewind函数
函数原型:void rewind(FILE *fp);
功能:直接使文件的当前读写位置在文件的开头。
rewind(fp) <==> fseek(fp, 0, SEEK_SET);
8、feof函数
函数原型:int feof(FILE *stream);
功能:判断文件的当前读写位置是否到达了文件的末尾。
返回值:如果文件的当前读写位置到达了文件的末尾,则返回1;否则,返回0
9、ferror函数
函数原型:int ferror(FILE *stream);
功能:判断的文件读写是否出错
返回值:如果文件的读写出错,则放回1;否则返回0