文件指针、文件描述符、文件句柄
**文件指针
通俗的说,文件指针就是指向文件的指针变量,定义说明文件指针的一般形式为:
FILE *指针变量标识符;其中FILE应为大写,它实际上是由系统定义的一个结构,该结构中含有文件名、文件状态和文件当前位置等信息。在编写源程序时不必关心FILE结构的细节。
在使用文件时,需要在内存中为其分配空间,用来存放文件的基本信息,给结构体类型是由系统定义的,FILE结构体与具体的编译器和系统有关。在VC + +中会这么定义FILE型,其声明如下:
struct _iobuf {
char*_ptr; //文件输入的下一个位置
int _cnt; //当前缓冲区的相对位置
char*_base; //指基础位置(应该是文件的其始位置)
int _flag; //文件标志
int _file; //文件的有效性验证
int _charbuf; //检查缓冲区状况,如果无缓冲区则不读取
int _bufsiz; //文件的大小
char*_tmpfname; //临时文件名
};
typedef struct _iobuf FILE;
1 文件的打开
函数FILE* fopen(const char *path,const char *mode);
头文件 stdio.h
参数:
Path:包含文件名的文件路径
Mode:打开文件的方式
对于mode,主要由r,w,a,+,b,t六个字符组合而成。
r:只读方式,文件必须存在
w:只写方式,若文件存在,则原有内容会被清除;若文件不存在,则会建立文件
a:追加方式打开只写文件,只允许进行写操作,若文件存在,则添加的内容放在文件末尾;若不存在,则建立文件
+:可读可写
b:以二进制方式打开文件
t:以文本方式打开文件(默认方式下以文本方式打开文件)
下面是常见的组合:
r:以只读的方式打开文件,只允许读,此文件必须存在,否则返回NULL,打开成功后返回文件指针,位置指针指向文件头部
r+:以可读可写的方式打开文件,允许读写,此文件必须存在,否则返回NULL,打开成功后返回文件指针,位置指针指向文件头部
rb+:以可读可写、二进制方式打开文件,允许读写,此文件必须存在,否则返回NULL,打开成功后返回文件指针,位置指针指向文件头部
rt+: 以可读可写、文本方式打开文件,允许读写,此文件必须存在,否则返回NULL,打开成功后返回文件指针,位置指针指向文件头部
w: 以只写的方式打开文件,只允许写,若文件存在,文件中原有内容会被清除;若文件不存在,则创建文件,打开成功后返回文件指针,位置指针指向文件头部
w+: 以读写的方式打开文件,允许读写,若文件存在,文件中原有内容会被清除;若文件不存在,则创建文件,打开成功后返回文件指针,位置指针指向文件头部
a: 以追加、只写的方式打开文件,只允许写。若文件存在,则追加的内容添加在文件末尾,若文件不存在,则创建文件。打开成功后返回文件指针,位置指针指向文件头部(注意很多书上或资料上讲述追加方式打开成功后位置指针指向文件末尾是错误的)
a+: 以追加、可读写的方式打开文件,允许读写。若进行读操作,则从头开始读;若进行写操作,则将内容添加在末尾。若文件不存在,则创建文件。打开成功后返回文件指针,位置指针指向文件头部。
其他方式类似。
下面讨论一下以二进制方式和文本方式打开文件有什么区别。
其实这两种方式打开文件并没有太大的区别,仅仅只有一点区别就是在处理某些特殊字符的时候。
以文本方式打开文件,若将数据写入文件,如果遇到换行符'\n'(ASII 值为10,0A),则会转换为回车—换行'\r\n'(ASII值为13,10,0D0A)存入到文件中,同样读取的时候,若遇到回车—换行,即连续的ASII值13,10,则自动转换为换行符。
而以二进制方式打开文件时,不会进行这样的处理。
还有如果以文本方式打开文件时,若读取到ASCII码为26(^Z)的字符,则停止对文件的读取,会默认为文件已结束,而以二进制方式读取时不会发生这样的情况。由于正常情况下我们手动编辑完成的文件是不可能出现ASCII码为26的字符,所以可以用feof函数去检测文件是否结束。以上所述的两点区别只在windows下存在,在unix下没有区别。
注意:1)在以追加方式打开文件时,位置指针指向文件的首部。
在这里区分一下位置指针和文件指针:
文件指针:指向存储文件信息的一个结构体的指针
位置指针:对文件进行读写操作时移动的指针
关于文件指针(FILE*)、文件描述符(fd)、文件句柄(HANDLE)之间的转换:
1、 fd与FILE*之间的相互转换
1) FILE*转fd
函数: int fileno(FILE *stream );
头文件: stdio.h
功能: 用来取得参数stream指定的文件流所使用的文件描述符
2) fd转FILE*
函数: FILE *fdopen(int fd, const char *mode);
头文件: stdio.h(windows下为io.h)
功能: fdopen用来取得参数fd(文件描述符)指定的文件流和mode(一种旗标)所使用的文件流
注意: 在关闭fclose(fp)后对应的fd会被关闭,相对的,在close(fd)之后,fclose(fp)会出错
2、 在windows下FILE*与HANDLE之间的转换
1) FILE* 转HANDLE
函数: long _get_osfhandle(int fd);
头文件: windows下为io.h
功能: _get_osfhandle用来取得参数fd(文件描述符)指定的文件流所使用的HANDLE(文件句柄)
2) HANDLE 转FILE*
函数: int _open_osfhandle (intptr_t osfhandle,int flags );
头文件: windows下为io.h
功能: _open_osfhandle用来取得参数osfhandle(文件句柄HANDLE)指定的文件流和flags(一种旗标_O_APPEND、 _O_RDONLY、 _O_TEXT )所使用的文件描述符