一、基于ANSI标准的I/O函数实现文件的读写
在ANSI标准下,进行文件的读写操作会在用户空间中自动为正在使用的文件开开辟内存缓冲区。如下图所示:
ANSI标准的C库函数建立在底层的系统调用之上,即C函数库额文件访问函数的实现中使用了低级文件I/O系统调用。ANSI标准的C库函数是为了减少使用系统调用的次数,提高效率,根据应用的不同采取缓冲机制,这样,在对磁盘文件进行读操作时,可以一次性的从文件中读处大量的数据到缓冲区中,以后对这部分数据的访问就不需要再使用系统调用了,即整个读写操作只需要少量的CPU状态的切换。
在应用编程层面,程序对流的操作体现在文件流指针FILE上,在操作一个文件前,需要打开该文件,而使用ANSIC库函数fopen()打开一个文件后,将返回一个文件流指针与文件关联,所有针对该文件的读写操作都通过该文件流指针完成,以下是应用层所能访问的结构体。
// come from /usr/include/stdio.h
typedef struct _IO_FILE FILE ; //对FILE进行了重定义
//come from /usr/include/libio.h
struct _IO_FILE
{
int _flags ;
char* _IO_read_ptr ; //如果以读打开,当前读指针
char* _IO_read_end ; //如果以读打开,读区域结束位置
char* _IO_read_base ;
char* _IO_write_base ; //如果以写打开,写区起始区域
char* _IO_write_ptr ; //如果以写打开,当前写指针
char* _IO_write_end ; //如果以写打开,写区域结束位置
char* _IO_buf_base ; //如果显示设置缓冲区,其起始位置
char* _IO_buf_end ; //如果显示设置缓冲区,其结束位置
...
int _fileno ;
}
缓冲区的三种类型:全缓冲区、行缓冲区和无缓冲区
1、全缓冲区:这种缓冲区默认大小为BUFSIZ,具体大小与系统定义有关。在缓冲区满或调用fflush()后才进行I/O系统调用操作。
2、行缓冲区:当遇到换行或者缓冲区满时,行缓冲区才刷新,大小根据系统有所差异,部分系统默认为128字节,标准I/O库将执行I/O系统调用操作。终端即行缓冲区。
3、不带缓冲区:标准I/O库不对字符进行缓存。
下面即为实现将用户输入的字符接收并写入test.txt文件,并显示出来的代码:
/*
*进行文件的读学操作
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAXSIZE 100
int main(int argc , char* argv[])
{
FILE *file ;
char buffer[128] , buffer1[10] ;
char state[MAXSIZE] ;
int length = 0 , i ;
printf("Please input the statement you want to write : ") ;
scanf("%s" , state) ;
length = strlen(state) ;
//打开文件
if((file = fopen(argv[1] , "w+")) == NULL)
{
perror("open") ;
exit(EXIT_FAILURE) ;
}
setvbuf(file , buffer , _IOLBF , 128) ; //设置缓冲区,一般情况下不需要,此处进行演示
fwrite(state , 1 , length , file ) ; //写入语句
fclose(file) ; //进行文件的关闭
//再次打开读出文件内容
if((file = fopen(argv[1] , "r")) == NULL)
{
perror("open") ;
exit(EXIT_FAILURE) ;
}
do
{
memset(buffer1 , \'\0\' , 10) ;
i = fread(buffer1 , 1 , 10 , file) ;
printf("%s" , buffer1) ;
}while(i == 10) ;
printf("\n") ;
fclose(file) ;
return 0 ;
}