¿Cuál es la diferencia entre los modos fopen "r+" y "rw+" en PHP?
(1)
Creo que ya has resuelto esto. Aunque supongo que quieres una respuesta autorizada.
Es cierto que la documentación no menciona
"rw+"
.
Sin embargo, hay algo mejor: ¡
código fuente PHP
!
La madriguera del conejo
Me costó mucho tratar de navegar el código fuente hasta que encontré la serie de artículos Código fuente de PHP para desarrolladores de PHP ( Parte 1 , Parte 2 , Parte 3 , Parte 4 ). Sé que los enlaces saltan entre dos sitios, esa serie es moderna. Por cierto, no encontré la Parte 5 anunciada.
Nota : Esos artículos son viejos, están hablando de PHP 5.4.
Veamos qué hace realmente
fopen
... caigamos en la madriguera del conejo ...
Primero nos fijamos en la
definición de
la
función
(que encontré siguiendo los consejos de la parte 2 vinculada anteriormente).
php_stream_open_wrapper_ex
que usa
php_stream_open_wrapper_ex
, que
encontré en otro lugar
, solo usa
_php_stream_open_wrapper_ex
que encontramos en
stream.c
.
¿Qué hace
_php_stream_open_wrapper_ex
con el
mode
?
Se lo pasa a
stream_opener
.
Buscando la definición de
stream_opener
me llevó al tipo
php_stream_wrapper_ops
en php_streams.h
.
La búsqueda de usos del tipo
php_stream_wrapper_ops
me
plain_wrapper.c
a
plain_wrapper.c
.
En realidad, hay muchas inicializaciones de
php_stream_wrapper_ops
que permiten abrir cosas diferentes.
Estamos viendo php_fopen_wrapper.c porque tiene una inicialización de
php_stream_wrapper_ops
donde
stream_opener
es
php_plain_files_stream_opener
.
Estamos llegando allí...
php_plain_files_stream_opener
está
más abajo en el mismo archivo
.
php_stream_fopen_rel
a
php_stream_fopen_rel
.
php_streams.h
define
php_stream_fopen_rel
utilizando
_php_stream_fopen
.
Que está de
vuelta en plain_wrapper.c
.
Finalmente,
_php_stream_fopen
llama a
php_stream_parse_fopen_modes
.
Lo que tomará la cadena y generará algunas banderas, ¡Yay!
mundo maravilloso
Echemos un vistazo a
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;
}
Para el resumen, esto es lo que hace (ignorando los detalles):
-
Toma el primer carácter del
mode
y comprueba si esr
,w
,a
,x
,c
. Si reconoce alguno de ellos, establece la bandera apropiada. De lo contrario, tenemos unFAILURE
. -
Busca
+
en algún lugar de la cadena y establece las banderas apropiadas. -
Busca
e
,t
(dependiendo de las directivas del preprocesador) en algún lugar de la cadena y establece los indicadores apropiados. -
Devolver el
SUCCESS
.
De vuelta al mundo real
Tu preguntaste:
¿Cuál es la diferencia entre los modos fopen "r +" y "rw +" en PHP?
Nada.
PHP solo se preocupa de que la cadena comience con
"r"
y tenga un
"+"
.
La
"w"
se ignora.
Nota final
: si bien es tentador jugar con él y escribir cosas como
"read+"
, tenga cuidado con eso, porque esas letras algún día podrían tener algún significado.
No sería compatible con versiones anteriores.
De hecho, en algún contexto,
"e"
ya tiene un significado.
En cambio, sugiero, atenerse a la documentación.
Gracias por la excusa para echar un vistazo al código fuente de PHP.
Muchas respuestas aquí en Stack Overflow usan
fopen($file, "rw+")
, pero el
manual
no enumera el modo
"rw+"
, solo está el modo
"r+"
(o modo
"w+"
).
Entonces me preguntaba,
¿qué hace el modo
"rw+"
?
¿Cuál es la diferencia entre
fopen($file,
"rw+"
o
"r+"
?
Estoy preguntando esto porque no hay documentación sobre el modo
"rw+"
.
Un enfoque es considerar que los modos son
aditivos
, pero no pude encontrar ninguna mención de los modos de combinación en la página del manual de
fopen
(además, ¿cuál es el sentido de combinar
"r"
con
"w+"
, si
"w+"
ya lo hace ¿legible?).
Pero lo más importante, el
modo
w+
trunca el archivo, mientras que
rw+
no lo trunca
(por
lo
tanto, no pueden ser aditivos).
Probablemente no haya modo
rw+
, a pesar de su uso por parte de los usuarios de Stack Overflow.
Tal vez funciona porque el analizador ignora la letra "w", ya que el modo
rw+
parece ser ===
r+
?
Para aclarar mi pregunta:
¿cuál es el modo
"rw+"
, es decir, cómo se diferencia de otros modos?
Solo recibí dos respuestas en los comentarios: ya sea que debería verificar la documentación (ya lo verifiqué y volví a verificar) y una respuesta incorrecta, que decía que es igual a
"w+"
(no lo es).
"w+"
trunca el archivo, mientras que
"rw+"
no.
Aquí hay un script para probar (demuestra que
w+
trunca el archivo, pero
rw+
no):
<?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;
?>