第九章读书笔记
知识点归纳
1、I/O库函数是一系列文件操作函数,,相比于系统调用,ta们能以适合应用程序的逻辑单元读/写文件。
系统函数:
-
open()
用于创建一个新的文件描述符
-
read()
读取文件,从文件描述符 fildes 相关联的文件里读入 nbytes 个字节的数据,并把它们放到数据区 buffer 中
-
write()
把缓冲区 buffer 的前 nbytes 个字节写入与文件描述符 fildes 关联的文件中
-
lseek()
用于改变读写操作时的位置指针
-
close()
终止文件描述符 fildes 与其对应文件之间的关联
I/O函数:
-
fopen()
用于对文件和终端的输入输出
-
fread()
从一个文件流里读取数据,数据从stream读到由ptr指定的数据缓冲区里面; fwirte(),从stream获取数据记录写到ptr中,返回值是成功写入的记录个数
-
fseek()
在文件流里面为下一次读写指定位置
-
fclose(),关闭指定的文流stream,使所有未写出的内容全部写出。
2、I/O库函数模式
"r+":表示读/写,不会截断文件。
"w+":表示读/写,但是会先截断文件;如果文件不存在,会创建文件。
"a+":表示通过追加进行读/写;如果文件不存在,会创建文件。
3、文件流缓冲
通过fopen()创建文件流之后,在对其执行任何操作之前,用户均可发出一个
setvbuf(FILE *stream, char *buf, int node, int size)
调用来设置缓冲区(buf)、缓冲区大小(size)和 缓冲方案(mode),它们必须是以下一个宏:
_IONBUF:无缓冲:从非缓冲流中写入(读取)的字符将尽快单独传输到文件(从文件传输)
_IOLBUF:行缓冲:遇到换行符,写入行缓冲流的字符以块的形式传输,如文件流stdout
_IOFBUF:全缓冲:文件流的正常缓冲方案,以块大小传出
问题与解决思路
实践内容
1、练习9.1 在如下程序中,通过一个系统调用来写每个字符是非常低效的。用一个write()系统调用来替换for循环。
原代码:
#include <fcntl.h>
int main(int argc, char *argv[]){
int fd;
int i, n;
char buf[4096];
if (argc < 2) exit(1);
fd = open(argv[1], o_RDONLY);
if (fd < 0) exit(2);
while (n = read(fd, buf, 4096)){
for (i = 0; i < n; i++){
write(1, &buf[i], 1);
}
}
}
编译中出现问题:
解决方法:
该问题是没有提供函数所需的库文件导致的,所以需要加上exit()和write()read()的库文件如下:
#include <stdlib.h>
#include <unistd.h>
参考Linux系统调用函数write()的用法,write()系统调用向指定的文件描述符内写入指定字节数的内容,函数原型为
ssize_t write(int fd, const void *buf, size_t count);
其中参数count表示最多写入的字节数,返回值表是真正写入的字节数。上述代码中将count设为1导致每次只能写入1bit,我们将其改为4096就可以免去循环的低效输出了,就如同系统调用read()一样。
更改之后的代码:
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]){
int fd;
int i, n;
char buf[4096];
if (argc < 2) exit(1);
fd = open(argv[1], o_RDONLY);
if (fd < 0) exit(2);
while (n = read(fd, buf, 4096)){
write(1, &buf[i], 4096);
}
}
ma