php fopen

¿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):

  1. Toma el primer carácter del mode y comprueba si es r , w , a , x , c . Si reconoce alguno de ellos, establece la bandera apropiada. De lo contrario, tenemos un FAILURE .

  2. Busca + en algún lugar de la cadena y establece las banderas apropiadas.

  3. Busca e , t (dependiendo de las directivas del preprocesador) en algún lugar de la cadena y establece los indicadores apropiados.

  4. 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; ?>