《信息安全系统设计与实现》第二周学习笔记
第九章 I/O库函数
I/O库函数与系统调用
每个I/O库函数的根都在对应的系统调用函数中
- 系统调用函数
open()
read()
write()
lseek()
close() - I/O库函数
fopen()
fread()
fwrite()
fseek()
fclose()
I/O库函数的算法
- fread算法:
(1)第一次调用fread()时候,FILE结构体的缓冲区是空的,fread()使用保存的文件描述符fd发出一个n =read(fd, fbuffer, BLKSIZE);
系统调用,用数据块填充内部的fbuf[]
(2)在随后的每次fread()的调用中,它都尝试满足来自FILE结构体内部缓冲区的调用 - fwrite算法:
fwrite算法与fread算法类似,只是数据传输方向不同 - fclose算法:
若以写的方式打开文件,fclose会先关闭文件流的局部缓冲区。然后,它会发出一个close(fd)系统调用来关闭FILE结构体中的文件描述符。最后,它会释放FILE结构体,并将FILE指针重置为NULL
I/O库模式
-
fopen()
fopen()中的模式参数可以指定为“r”,“w”,“a”,分别代表读,写,追加,具体含义如下:
r:读
w: 写
a:追加
r+:读/写,不会截断文件
w+:读/写,会先截断文件;如果文件不存在,会创建文件
a+:通过追加进行读/写;如果文件不存在,会创建文件 -
字符模式I/O
int fgetc(FILE *fp); // get achar from fp, cast to int(从指针fp获取achar,强制转换为整型)
int ungetc(int c, FILE *fp); // push a prviously char got by fgetc() back to stream(将fgetc()获得的一个明显的字符推回到流中)
int fputc(int c, FILE *fp); // put a char to fp(将字符放入指针fp)
-
行模式I/O
char *fgets(char *buf, int size, FILE *fp);(从fp中读取最多的为一行(以\n结尾)的字符)
int fputs(char *buf,FILE *fp);(将buf的一行写入fp中)
-
格式化I/O
格式化输入:(FMT=格式字符串)
scanf(char *FMT,&items);
fscanf(fp, char *FMT,&items); //from file stream
格式化输出:
printf(char *FMT,items); //to stdout
fprintf(fp,char *FMT,items); //to file stream
- 内存中的转换函数
sscanf(buf,FMT,&items);
sprintf(buf, FMT, items);
-
其他I/O库函数
fseek()、ftell()、rewind():更该文件流中的读/写字节位置
feof()、ferr()、fileno():测试文件流状态
fdopen():用文件描述符打开文件流
freopen():以新名称重新打开现有的流
setbuf()、setvbuf():设置缓冲方案
popen():创建管道,复刻子进程来调用sh -
限制混合fread-fwrite
当某文件同时进行读、写操作时,会限制混合使用fread()和fwrite(),注意两者之间至少有一个fseek()或者ftell()
文件流缓冲
(1)无缓冲:从非缓冲流中写入或读取的字符将尽快单独传输到文件或从文件中传输
(2)行缓冲:遇到换行符时,写入行缓冲流的字符以块的形式传输
(3)全缓冲:写入全缓冲流或从中读取的字符以块大小传输到文件或从文件传输。这是文件流的正常缓冲方案。通过fopen()创建文件流之后,在执行任何操作之前,用户均可发出一个 setvbuf(FILE *stream,char *buf , int node,int size)
变参函数
在I/O库函数中 printf()相当独特,多种类型的可变数量参数都可以调用它
GPT苏格拉底挑战
- I/O库函数的算法
- 文件流缓冲
遇到的问题及解决方法
- 问题:对于I/O库函数和系统调用函数的异同有疑惑,它们的功能相近,样子也差不多,那么它们有什么区别
- GPT的回答:
实践(小写转大写)
- 截图:
代码: