第九章 I/O库函数
I/O库函数与系统调用
-
系统调用函数
-
open()
-
read()
-
write()
-
lseek()
-
close()
-
-
I/O库函数
-
fopen()
-
fread()
-
fwrite()
-
fseek()
-
fclose()
-
I/O库函数的算法
-
fread算法:
-
第一次调用fread()时候,FILE结构体的缓冲区是空的,fread()使用保存的文件描述符fd发出一个
n =read(fd, fbuffer, BLKSIZE);
系统调用,用数据快填充内部的fbuf[]。 -
在随后的每次fread()的调用中,它都尝试满足来自FILE结构体内部缓冲区的调用
-
-
fwrite算法:
- fwrite算法与fread算法类似,只是数据传输方向不同
-
fclose算法:
- 若以写的方式打开文件,fclose会先关闭文件流的局部缓冲区。然后,它会发出一个close(fd)系统调用来关闭FILE结构体中的文件描述符。最后,它会释放FILE结构体,并将FILE指针重置为NULL
使用I/O数据库或系统调用
在fread()和fwrite()的一些实现中,例如在GNU libc库中,如果请求的大小以BLKSIZE为单位,它们可以使用系统调用将以BLKSIZE为单位的数据直接从内核传输到用户指定的缓冲区。
I/O库模式
-
fopen()
fopen()中的模式参数:
-
r:读
-
w: 写
-
a:追加
-
r+:读/写,不会截断文件
-
w+:读/写,会先截断文件;如果文件不存在,会创建文件
-
a+:通过追加进行读/写;如果文件不存在,会创建文件
-
-
字符模式I/O
int fgetc(FILE *fp); // get achar from fp, cast to int
返回值:返回读取到的字符的整型表示,若已到达文件末尾或发生错误,则返回特定值 EOF(-1)int ungetc(int c, FILE *fp); // push a prviously char got by fgetc() back to stream
返回值:成功推回字符则返回推回的字符 c 的整型表示,推回失败则返回特定值 EOF(-1)。int fputc(int c, FILE *fp); // put a char to fp
返回值:成功写入字符则返回写入的字符 c 的整型表示,写入失败则返回特定值 EOF(-1)。
实践:将文本文件中的字母由小写转换成大写
原文件(input.txt)中的内容
main.c中的内容
代码如下:
操作过程
转换后,输出文件(output.txt)中的内容
-
行模式I/O
char *fgets(char *buf, int size, FILE *fp)
:从fp中读取最多的为一行(以\n结尾)的字符
int fputs(char *buf,FILE *fp)
:将buf的一行写入fp中 -
格式化I/O
-
格式化输入:
scanf(char *FMT,&items); fscanf(fp, char *FMT,&items);
-
格式化输出:
printf(char *FMT,items); fprintf(fp,char *FMT,items);
-
-
内存中的转换函数
sscanf(buf,FMT,&items); sprintf(buf, FMT, items);
在这里,sscanf()和sprintf()并非I/O函数,而是内存中的数据转换函数。
-
其他I/O库函数
-
fseek()、ftell()、rewind():更该文件流中的读/写字节位置
-
feof()、ferr()、fileno():测试文件流状态
-
fdopen():用文件描述符打开文件流
-
freopen():以新名称重新打开现有的流
-
setbuf()、setvbuf():设置缓冲方案
-
popen():创建管道,复刻子进程来调用sh
-
-
限制混合fread-fwrite
- 当某文件同时进行读、写操作时,会限制混合使用fread()和fwrite(),注意两者之间至少有一个fseek()或者ftell()
-
文件流缓冲
-
无缓冲:从非缓冲流中写入或读取的字符将尽快单独传输到文件或从文件中传输
-
行缓冲:遇到换行符时,写入行缓冲流的字符以块的形式传输
-
全缓冲:写入全缓冲流或从中读取的字符以块大小传输到文件或从文件传输。
-
通过fopen()创建文件流之后,在执行任何操作之前,用户均可发出一个
setvbuf(FILE *stream,char *buf , int node,int size)
调用来设置缓冲区(buf)、缓冲区大小(size)和缓冲区方案(mode),它们必须是一下以下一个宏:-
_IONBUF:无缓冲
-
_IOLBUF:行缓冲
-
_IOFBUF:全缓冲
-
-
-
变参函数
- 在I/O库函数中,printf()相当独特,多种不同类型的可变数量参数都可以调用它
苏格拉底挑战
-
关于I/O库函数与系统调用的苏格拉底挑战
-
关于fread算法的苏格拉底挑战
遇到的问题
问题:关于字符模式I/O,字符编码和字符模式I/O之间有何联系?
解决方法:使用GPT进行了解