PHP 中的 fopen 模式 "r+" 和 "rw+" 有什么区别?
What is the difference between fopen modes "r+" and "rw+" in PHP?
Stack Overflow 中的许多答案都使用 fopen($file, "rw+")
,但是 manual 没有列出 "rw+"
模式,只有 "r+"
模式(或 "w+"
模式).
所以我想知道,"rw+"
模式有什么作用? fopen($file,
"rw+"
或 "r+"
之间有什么区别? 我问这个是因为没有关于 "rw+"
模式的文档。
一种方法是考虑模式是加法,但我在fopen
手册页中找不到任何关于组合模式的提及(此外,什么是将 "r"
与 "w+"
结合起来的意义,如果 "w+"
已经使其可读?)。但最重要的是,w+
模式会截断文件,而 rw+
不会截断文件 (因此,它们不能相加)。可能没有 rw+
模式,尽管它被 Stack Overflow 用户使用。也许它有效是因为解析器忽略了 "w" 字母,因为 rw+
模式似乎是 === r+
?
澄清我的问题:什么是"rw+"
模式,即它与其他模式有何不同?我在评论中只收到了两个答案:要么我应该检查文档(我已经检查并重新检查)和一个错误的答案,它说它等于 "w+"
(它不是)。 "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;
?>
我想你已经很清楚了。虽然我猜,你想要权威的答案。
文档确实没有提到"rw+"
。然而,还有更好的东西:PHP source code!
兔子洞
在找到 PHP 系列文章 PHP 开发人员的源代码 (Part 1, Part 2, Part 3, Part 4) 之前,我很难尝试浏览源代码。 我知道两个站点之间的链接跳转,那个系列很时髦。对了,我没找到公布的Part 5
注:那些文章都是老的,说的是PHP5.4.
让我们看看 fopen
到底做了什么...让我们掉进兔子洞...
首先我们看function definition (which I found following the advice of the linked part 2 above). I notice it uses php_stream_open_wrapper_ex
, which I found elsewhere, it just uses _php_stream_open_wrapper_ex
which we find in stream.c.
_php_stream_open_wrapper_ex
和 mode
有什么关系? It passes it to stream_opener
.
寻找 stream_opener
的定义让我找到了类型 php_stream_wrapper_ops
in php_streams.h。
Searching for uses of the type php_stream_wrapper_ops
leaded me to plain_wrapper.c.
php_stream_wrapper_ops
实际上有很多初始化允许打开不同的东西。我们正在查看 php_fopen_wrapper.c,因为它具有 php_stream_wrapper_ops
的初始化,其中 stream_opener
是 php_plain_files_stream_opener
。
我们快到了...
php_plain_files_stream_opener
是 further down in the same file. It delegates to php_stream_fopen_rel
.
php_streams.h
defines php_stream_fopen_rel
by using _php_stream_fopen
. Which is back on plain_wrapper.c.
最后,_php_stream_fopen
calls php_stream_parse_fopen_modes
。这将获取字符串并输出一些标志,耶!
仙境
让我们看看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;
}
对于摘要,这是它的作用(忽略细节):
它取mode
的第一个字符并检查它是否是r
、w
、a
、x
、 c
。如果它识别出其中任何一个,它就会设置适当的标志。否则我们有 FAILURE
.
它在字符串中的某处查找 +
并设置适当的标志。
它在字符串的某处查找 e
、n
和 t
(取决于预处理器指令)并设置适当的标志。
ReturnSUCCESS
.
回到现实世界
您问的是:
What is the difference between fopen modes “r+” and “rw+” in PHP?
没有。 PHP只关心字符串以"r"
开头,有一个"+"
。 "w"
被忽略。
最后的说明:虽然很想玩弄它并写一些像 "read+"
这样的东西,但要小心,因为这些字母有一天可能会有一些意义。它不会向前兼容。事实上,在某些上下文中,"e"
已经具有了意义。相反,我建议坚持文档。
感谢您提供查看 PHP 源代码的借口。
Stack Overflow 中的许多答案都使用 fopen($file, "rw+")
,但是 manual 没有列出 "rw+"
模式,只有 "r+"
模式(或 "w+"
模式).
所以我想知道,"rw+"
模式有什么作用? fopen($file,
"rw+"
或 "r+"
之间有什么区别? 我问这个是因为没有关于 "rw+"
模式的文档。
一种方法是考虑模式是加法,但我在fopen
手册页中找不到任何关于组合模式的提及(此外,什么是将 "r"
与 "w+"
结合起来的意义,如果 "w+"
已经使其可读?)。但最重要的是,w+
模式会截断文件,而 rw+
不会截断文件 (因此,它们不能相加)。可能没有 rw+
模式,尽管它被 Stack Overflow 用户使用。也许它有效是因为解析器忽略了 "w" 字母,因为 rw+
模式似乎是 === r+
?
澄清我的问题:什么是"rw+"
模式,即它与其他模式有何不同?我在评论中只收到了两个答案:要么我应该检查文档(我已经检查并重新检查)和一个错误的答案,它说它等于 "w+"
(它不是)。 "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;
?>
我想你已经很清楚了。虽然我猜,你想要权威的答案。
文档确实没有提到"rw+"
。然而,还有更好的东西:PHP source code!
兔子洞
在找到 PHP 系列文章 PHP 开发人员的源代码 (Part 1, Part 2, Part 3, Part 4) 之前,我很难尝试浏览源代码。 我知道两个站点之间的链接跳转,那个系列很时髦。对了,我没找到公布的Part 5
注:那些文章都是老的,说的是PHP5.4.
让我们看看 fopen
到底做了什么...让我们掉进兔子洞...
首先我们看function definition (which I found following the advice of the linked part 2 above). I notice it uses php_stream_open_wrapper_ex
, which I found elsewhere, it just uses _php_stream_open_wrapper_ex
which we find in stream.c.
_php_stream_open_wrapper_ex
和 mode
有什么关系? It passes it to stream_opener
.
寻找 stream_opener
的定义让我找到了类型 php_stream_wrapper_ops
in php_streams.h。
Searching for uses of the type php_stream_wrapper_ops
leaded me to plain_wrapper.c.
php_stream_wrapper_ops
实际上有很多初始化允许打开不同的东西。我们正在查看 php_fopen_wrapper.c,因为它具有 php_stream_wrapper_ops
的初始化,其中 stream_opener
是 php_plain_files_stream_opener
。
我们快到了...
php_plain_files_stream_opener
是 further down in the same file. It delegates to php_stream_fopen_rel
.
php_streams.h
defines php_stream_fopen_rel
by using _php_stream_fopen
. Which is back on plain_wrapper.c.
最后,_php_stream_fopen
calls php_stream_parse_fopen_modes
。这将获取字符串并输出一些标志,耶!
仙境
让我们看看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;
}
对于摘要,这是它的作用(忽略细节):
它取
mode
的第一个字符并检查它是否是r
、w
、a
、x
、c
。如果它识别出其中任何一个,它就会设置适当的标志。否则我们有FAILURE
.它在字符串中的某处查找
+
并设置适当的标志。它在字符串的某处查找
e
、n
和t
(取决于预处理器指令)并设置适当的标志。Return
SUCCESS
.
回到现实世界
您问的是:
What is the difference between fopen modes “r+” and “rw+” in PHP?
没有。 PHP只关心字符串以"r"
开头,有一个"+"
。 "w"
被忽略。
最后的说明:虽然很想玩弄它并写一些像 "read+"
这样的东西,但要小心,因为这些字母有一天可能会有一些意义。它不会向前兼容。事实上,在某些上下文中,"e"
已经具有了意义。相反,我建议坚持文档。
感谢您提供查看 PHP 源代码的借口。