当我们用c语言的库函数打开一个文件的时候,fopen的第二个参数指定了打开的方式.有r,w,a,r+,w+,a+等等… 这些mode具体区别是什么呢,下面我给大家说明一下
参考一下glibc-2.23的fopen源码:
_IO_FILE * _IO_new_file_fopen (_IO_FILE *fp, const char *filename, const char *mode,
int is32not64)
{
int oflags = 0, omode;
int read_write;
int oprot = 0666;
int i;
_IO_FILE *result;
#ifdef _LIBC
const char *cs;
const char *last_recognized;
#endif
if (_IO_file_is_open (fp))
return 0;
switch (*mode)
{
case 'r':
omode = O_RDONLY;
read_write = _IO_NO_WRITES;
break;
case 'w':
omode = O_WRONLY;
oflags = O_CREAT|O_TRUNC;
read_write = _IO_NO_READS;
break;
case 'a':
omode = O_WRONLY;
oflags = O_CREAT|O_APPEND;
read_write = _IO_NO_READS|_IO_IS_APPENDING;
break;
default:
__set_errno (EINVAL);
return NULL;
}
#ifdef _LIBC
last_recognized = mode;
#endif
for (i = 1; i < 7; ++i)
{
switch (*++mode)
{
case '\0':
break;
case '+':
omode = O_RDWR;
read_write &= _IO_IS_APPENDING;
#ifdef _LIBC
last_recognized = mode;
#endif
continue;
case 'x':
oflags |= O_EXCL;
#ifdef _LIBC
last_recognized = mode;
#endif
continue;
case 'b':
#ifdef _LIBC
last_recognized = mode;
#endif
continue;
case 'm':
fp->_flags2 |= _IO_FLAGS2_MMAP;
continue;
case 'c':
fp->_flags2 |= _IO_FLAGS2_NOTCANCEL;
continue;
case 'e':
#ifdef O_CLOEXEC
oflags |= O_CLOEXEC;
#endif
fp->_flags2 |= _IO_FLAGS2_CLOEXEC;
continue;
default:
continue;
}
break;
}
result = _IO_file_open (fp, filename, omode|oflags, oprot, read_write,
is32not64);
return result;
}
这里只保留了和mode有关的代码.
首先会判断第一个字符: r: 只能读 w: 只能写 a: 只能写,而且标记了append的flag,也就是在文件末尾追加写,若已经存在会保留原文件.
接着判断了后面的几个字符: +: 可读可写,只是修改了 open系统调用的omode,而open函数的flag不变,所以可以得出: 有+的mode除了打开文件后可读可写,和没有+的mode没有什么区别了
也就是 r+的话,文件不存在还是无法打开,若打开成功之后我们还可以进行写操作,(没有+只能读) w+的话,文件存在,仍然会直接清空,打开之后除了写操作我们还可以进行读操作 (没有+只能进行写操作) a+ 同理,只是多了打开成功之后的 可读可写
之后大家可以动手验证一下上面的说法
|