PHP中fopen模式“r +”和“rw +”有什么区别?

在堆栈溢出使用fopen($file, "rw+")许多答案,但手册没有列出"rw+"模式,只有"r+"模式(或"w+"模式)。

所以我想知道, "rw+"模式是做什么的? fopen($file, "rw+""r+"什么区别?我这样问是因为在"rw+"模式下没有文档。

一种方法是考虑到这些模式是加法的 ,但是在fopen手册页中我找不到任何组合模式(除了"r" "w+""w+"结合的意义是什么,如果"w+"已经使它可读?)。 但最重要的是, w+模式会截断文件,而rw+不会截断它 (因此,它们不能被添加)。 可能没有rw+模式,尽pipeStack Overflow用户使用它。 也许这是因为parsing器忽略了“w”字母,因为rw+模式似乎是=== r+

为了澄清我的问题: 什么是"rw+"模式 ,也就是说,它与其他模式有什么不同? 我在评论中只收到了两个答案:或者我应该检查文档(我已经检查并重新检查)和一个错误的答案,它说它等于"w+" (不是)。 "w+"截断文件,而"rw+"不。

这是一个testing脚本(它certificatew+截断文件,但rw+不):

 <?php $file = "somefile"; $fileOpened = fopen($file, "w"); fwrite($fileOpened, "0000000000000000000"); fclose($fileOpened); $fileOpened = fopen($file, "rw+"); fwrite($fileOpened, "data"); fclose($fileOpened); $fileOpened = fopen($file, "r"); $output = fgets($fileOpened); echo "First, with 'rw+' mode:<br>".$output; $fileOpened = fopen($file, "w+"); fwrite($fileOpened, "data"); fclose($fileOpened); $fileOpened = fopen($file, "r"); $output = fgets($fileOpened); echo "<br><br><br>Now with only 'w+' mode:<br>".$output; ?> 

我想你已经明白了这一点。 虽然我猜,你想要权威的答案。

确实,文档没有提到"rw+" 。 然而,还有更好的东西: PHP源代码 !


兔子洞

我很难试图浏览源代码,直到我find文章系列PHP的PHP开发人员源代码( 第1 部分 , 第2 部分 , 第3 部分 , 第4部分 )。 我知道两个网站之间的链接跳转,那个系列就像那样。 顺便说一下,我没有find宣布的第5部分。

注意 :这些文章是老的,他们正在谈论PHP 5.4。

让我们看看fopen究竟做了什么…让我们陷入兔子洞

首先我们看看函数的定义 (我发现上面的链接部分2的build议)。 我注意到它使用php_stream_open_wrapper_ex ,我在其他地方find它,它只是使用_php_stream_open_wrapper_ex我们在stream.c中find。

_php_stream_open_wrapper_exmode做什么? 它将它传递给stream_opener

寻找stream_opener的定义把我带到php_stream_wrapper_ops中的typesphp_stream_wrapper_ops 。

searchphp_stream_wrapper_opstypes的用法使我变成了plain_wrapper.c 。

实际上有很多php_stream_wrapper_ops的初始化允许打开不同的东西。 我们正在看php_fopen_wrapper.c,因为它有一个php_stream_wrapper_ops的初始化,其中stream_openerphp_plain_files_stream_opener

我们到了那里…

php_plain_files_stream_opener 进一步在同一个文件中 。 它委托给php_stream_fopen_rel

php_streams.h使用_php_stream_fopen 定义php_stream_fopen_rel 。 这是在plain_wrapper.c 。

最后, _php_stream_fopen调用php_stream_parse_fopen_modes 。 这将采取string和输出一些标志,耶!


仙境

让我们看看php_stream_parse_fopen_modes

 PHPAPI int php_stream_parse_fopen_modes(const char *mode, int *open_flags) { int flags; switch (mode[0]) { case 'r': flags = 0; break; case 'w': flags = O_TRUNC|O_CREAT; break; case 'a': flags = O_CREAT|O_APPEND; break; case 'x': flags = O_CREAT|O_EXCL; break; case 'c': flags = O_CREAT; break; default: /* unknown mode */ return FAILURE; } if (strchr(mode, '+')) { flags |= O_RDWR; } else if (flags) { flags |= O_WRONLY; } else { flags |= O_RDONLY; } #if defined(O_CLOEXEC) if (strchr(mode, 'e')) { flags |= O_CLOEXEC; } #endif #if defined(O_NONBLOCK) if (strchr(mode, 'n')) { flags |= O_NONBLOCK; } #endif #if defined(_O_TEXT) && defined(O_BINARY) if (strchr(mode, 't')) { flags |= _O_TEXT; } else { flags |= O_BINARY; } #endif *open_flags = flags; return SUCCESS; } 

对于抽象,这就是它所做的(忽略细节):

  1. 它取mode的第一个字符,并检查它是否是rwaxc 。 如果它承认任何这些,它设置适当的标志。 否则,我们有一个FAILURE

  2. 它在string的某个地方查找并设置适当的标志。

  3. 它查找string中某处的ent (取决于预处理器指令)并设置相应的标志。

  4. 回报SUCCESS


回到现实世界

你问:

PHP中fopen模式“r +”和“rw +”有什么区别?

没有。 PHP只关心string以"r"开始并且有一个"+""w"被忽略。

最后说明 :虽然很喜欢玩这个游戏,写"read+"类的东西,但要小心,因为这封信有一天会有一些意义。 它不会向前兼容。 实际上,在某些情况下, "e"已经有了意义。 相反,我build议,坚持文件。


感谢您的借口来看看PHP源代码。