文件流指针
在应用编程层面,程序对流的操作体现在文件流指针FILE上,在操作一个文件前,需要打开该文件,而使用ANSI C库函数fopen()打开一个文件后,将返回一个文件流指针与该文件关联,所有针对该文件的读写操作都通过该文件流指针完成,以下是应用层所能访问的FILE结构体,因此,结构体成员可以在用户空间中访问。
typedef struct _IO_FILE FILE;
struct _IO_FILE{
int _flags;
char* _IO_read_ptr; //如果以读打开,当前读指针
char* _IO_read_end; //如果以读打开,读区域结束位置
char* _IO_read_base; //Start of putback+get area
char* _IO_write_base; //如果以写打开,写区起始区
char* _IO_write_ptr; //如果以写打开,当前写指针
char* _IO_write_end; //如果以写打开,写区域结束位置
char* _IO_buf_base; //如果显示设置缓冲区,其起始位置
char* _IO_buf_end; //如果显示设置缓冲区,其结束位置。
…
int _fileno; //文件描述符
…
}
在此结构体中,包含了I/O库为管理该流所需要的所有信息,如用于实现I/O的文件描述符、指向流缓冲区的指针、缓冲区的长度、当前在缓冲区中的字符数和出错标志等。
下面是打印了一个打开的文件流指针成员信息的示例程序,在此程序中,使用标准的C库函数实现了文件的复制操作,在复制过程中,实时打印当前的读写位置以及缓冲区信息。
//ptr_struct_file.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define prt(CONTENT,MSG) printf(CONTENT":\t%p\n",MSG)
int main(int argc,char *argv[])
{
FILE *fp_src,*fp_des;
char buffer[10],buffer1[128];
int i;
if((fp_src=fopen(argv[1],“r+”))==NULL) //读写方式打开,文件必须存在
{
perror(“open1”);
exit(EXIT_FAILURE);
}
if((fp_des=fopen(argv[2],“w+”))==NULL) //读写方式打开文件,文件必须存在
{
perror(“open2”);
exit(EXIT_FAILURE);
}
setvbuf(fp_src,buffer1,_IOLBF,128); //显示设置缓冲区位置及类型,在一般应用中不需要,演示示例
do
{
prt("src_IO_read_ptr",fp_src->_IO_read_ptr);//源文件读位置
prt("_IO_read_end",fp_src->_IO_read_end);
prt("_IO_read_base",fp_src->_IO_read_base);
prt("src_IO_write_ptr",fp_src->_IO_write_ptr);//源文件写位置
prt("_IO_write_base",fp_src->_IO_write_base);
prt("_IO_write_end",fp_src->_IO_write_end);
prt("_IO_buf_base\t",fp_src->_IO_buf_base);//源文件缓冲位置
prt("_IO_buf_end\t",fp_src->_IO_buf_end);
memset(buffer,'\0',10);
i=fread(buffer,1,10,fp_src); //读
fwrite(buffer,1,i,fp_des); //写
prt("des_IO_read_ptr",fp_des->_IO_read_ptr); //目标文件读位置
prt("des_IO_write_ptr",fp_des->_IO_write_ptr); //目标文件写位置
printf("\n");
}while(i==10);
fclose(fp_src);
fclose(fp_des);
}
由示例结果可知,对文件的读写并不更新该结构体的所有成员,这与打开及操作的方式相关。
来源:《Linux高级程序设计》人民邮电出版社 杨宗徳 吕光宏 刘雍 编著