第九章总结要点
1.I/O库函数与系统调用
系统调用函数:open()、read()、write()、lseek()、close();
I/O库函数:fopen()、fread()、fwrite()、flseek()、fclose()。
I/O库函数一一对应地依赖于系统调用函数。
2、I/O库函数的算法
-2.1 fread算法
在第一次调用fread()时,FILE结构体的缓冲区是空的,fread()使用保存的文件描述符fd发出一个系统调用,用数据块填充内部的fbuf[]。然后,它会初始化fbu[]的指针、计数器和状态变量,以表明内部缓冲区中有一个数据块。接着,通过将数据复制到程序的缓冲区,尝试满足来自内部缓冲区的fread()调用。如果内部缓冲区没有足够的数据,则会再发出一个read()系统调用来填充内部缓冲区,将数据从内部缓冲区传输到程序缓冲区,直到满足所需的字节数(或者文件无更多数据)。将数据复制到程序的缓冲区之后,它会更新内部缓冲区的指针、计数器等,为下一个 fread()请求做好准备。然后,它会返回实际读取的数据对象数量。
-2.2 fwrite算法
fwrite()算法与fread()算法相似,但数据传输方向不同。每次调动fwrite()时,它将数据写入缓冲区,并调整缓冲区的指针、计数器和状态变量,以跟踪缓冲区中的字节数。如果缓冲区已满,则发出write()系统调用,将整个缓冲区写入操作系统内核。
-2.3 fclose()算法
fwrite()在每次被调用的时候,它将数据写入内部缓冲区,并调整缓冲区的指针、计数器和状态变量,以跟踪缓冲区的字节数。如果缓冲区已满,则发出write()系统调用,将整个缓冲区写入操作系统内核。()fclose函数可以关闭文件流的局部缓冲区,然后,它会发出一个close(fd)系统调用来关闭 FILE 结构体中的文件描述。最后释放 FILE 结构体,并将 FILE 指针重置为NULL。
3.文件缓流冲
1.无缓冲
2.行缓冲
3.全缓冲 通过fopen()创建文件流之后,在对其执行任何操作之前,用户均可发出一个 setvbuf(FILE *stream, char *buf, int node, int size) 调用来设置缓冲区(buf)、缓冲区大小(size)和缓冲方案(mode),它们必须是以下一个宏:
IONBUF:无缓冲
OLBUF:行缓冲
IOFBUF:全缓冲 此外,还有其他的setbuf()函数,是setvbuf()的变体。对于行缓冲流或全缓冲流,可用fflush(stream)立即清除流的缓冲区。
3.C语言库函数访问文件
—3.1文件的创建与打开:FILE *fopen(const char *filename,const char *mode)
filename:文件名
mode:打开模式
—3.2常见的打开方式:r,rb 只读
w,wb 只写,如果文件不存在就创建
a,ab 追加,如果文件不存在就创建
r+,r+b,rb+ 读写方式打开
w+,w+b,wh+ 读写方式打开,文件不存在则创建
a+,a+b,ab+ 读和追加方式打开,文件不存在则创建
—3.3读文件:(b表示二进制文件)
size_t fread(void *ptr,size_t size,size_t n,FILE *stream)
stream:源文件
n:读取字段数
size: 每个字段的字节数
ptr:目标字符数组
返回实际读取的字节数
—3.4写文件:size_t fwrite(const void *ptr,size_t size,size_t n,FILE *stream)
ptr:源数组
n:字段数
size:字段的字节数
stream:目标文件
返回实际写入字段数
问题与解决思路:
1.文本文件和二进制文件
所谓的文本文件,就是按照字符的编码规则(比如ASCII),1:1的根据你敲的字符形成的机器码文件。后缀习惯是以.txt结尾。一个典型的文本编辑器就是大家熟悉的记事本程序(notepad.exe)。
二进制文件是可以认为是所有非文本文件都称之为二进制文件。
要打开二进制文件,需要有形成这类文件的程序的内置的解析器,才能解读。这也解释了为什么不同的文件比如pdf,docx等文件,在编程的时候,必须要有相应的文档解析类函数来完成的原因了。
当然你完全可以用二进制方式打开任何一个文本文件,因为底层上就是那些代码,你只需要读取每一个字节,查找转化成相应字符予以显示就可以了,因为是你知道ASCII表的规则。