fopen模式之间有什么区别" r +"和" rw +"用PHP?

时间:2017-05-05 05:30:58

标签: php fopen

Stack Overflow中的许多答案都使用fopen($file, "rw+"),但manual没有列出"rw+"模式,只有"r+"模式(或"w+"模式)。

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

一种方法是考虑模式是添加,但我无法在fopen手册页中找到任何关于组合模式的提及(此外,'将"r""w+"结合起来的意义,如果"w+"已经使其可读?)。但最重要的是, w+模式会截断文件,而rw+不会截断文件(因此,它们不能添加)。尽管Stack Overflow用户使用它,但可能没有rw+模式。也许它有效,因为解析器忽略了" w"字母,因为rw+模式似乎是=== r+

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

这是一个用于测试的脚本(它证明w+会截断文件,但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; 
?>

1 个答案:

答案 0 :(得分:68)

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

文档确实没有提及"rw+"。然而,有更好的东西:PHP source code

兔子洞

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

注意:这些文章很旧,他们在讨论PHP 5.4。

让我们看看fopen实际上做了什么......让我们陷入兔子洞......

首先我们看看Part 4(我根据上面链接第2部分的建议找到了)。我注意到它使用function definition,我php_stream_open_wrapper_ex,它只使用我们在found elsewhere中找到的_php_stream_open_wrapper_ex

_php_stream_open_wrapper_exmode做了什么? stream.c

寻找stream_opener的定义将我带到It passes it to stream_opener类型。

php_stream_wrapper_ops in php_streams.h诱使我Searching for uses of the type php_stream_wrapper_ops

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

我们到了那里......

php_plain_files_stream_openerplain_wrapper.cfurther down in the same file

It delegates to php_stream_fopen_rel使用_php_stream_fopen。这是php_streams.h defines php_stream_fopen_rel

最后,back on plain_wrapper.c。这将取出字符串并输出一些标志,耶!

仙境

让我们看看_php_stream_fopen calls 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的第一个字符,并检查它是rwax,{{1} }。如果它识别出任何一个,它会设置适当的标志。否则我们有c

  2. 它在字符串中的某处查找FAILURE并设置相应的标记。

  3. 它在字符串中的某处查找+en(取决于预处理程序指令)并设置相应的标记。

  4. 返回t

  5. 回到现实世界

    你问:

      

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

    无。 PHP只关心字符串以SUCCESS开头并且有"r""+"被忽略。

    最后的注意事项:虽然很有可能与它一起玩并编写像"w"这样的东西,但要小心,因为那些信可能有一天会有一些意义。它不会向前兼容。事实上,在某些情况下,"read+"已经有了意义。相反,我建议,坚持文档。

    感谢您借口查看PHP源代码。