PHP-TUT-15 Ficheros en disco

Facebooktwittergoogle_pluslinkedinmailFacebooktwittergoogle_pluslinkedinmail

archivos_y_directorios_phpEn este artículo vamos a conocer las posibilidades que PHP incorpora para la gestión de ficheros. Veremos cómo un script de PHP puede almacenar, recuperar y/o eliminar cierta información general en archivos de texto plano que se manejarán en el lado del servidor.

LOS FICHEROS

PHP permite la gestión de ficheros de texto plano, es decir, sin un formato específico, que se almacenan en el lado del servidor. Este tipo de ficheros pueden ser usados para almacenar ciertos datos acerca del tráfico en la red, o de los usuarios que se han conectado, etc. Además, permite la gestión de otros ficheros adicionales (sesiones, cookies del cliente, etc.) pero eso es tema para otros artículos. Aquí nos vamos a ocupar de ficheros que puedes grabar y/o leer en la forma que sea necesario. Cuando se trabaja con un fichero para almacenar o recuperar cierto tipo de información se llevan a cabo, de modo genérico, tres operaciones básicas:

  • La apertura del fichero.
  • La lectura o escritura en el mismo.
  • El cierre del fichero.

En ese sentido la gestión de ficheros desde PHP es similar al manejo de ficheros tradicionales de papel en un archivador de oficina de los de toda la vida. En este post aprenderemos a realizar todas estas operaciones.

ABRIR FICHEROS

Para abrir un fichero recurrimos a la función fopen(), que recibe dos argumentos. El primero es el nombre del fichero que es necesario abrir, con su ruta, si ésta no es la misma que aquélla donde se encuentra grabado el script. El segundo argumento es el modo en que queremos abrir el fichero. Éste dependerá de lo que vayamos a hacer con el mismo. Existen trece modos posibles para abrir un fichero, que aparecen recogidos en la tabla que aparece a continuación:

MODOS DE APERTURA DE FICHEROS
MODO SIGNIFICADO
a Abre el fichero para añadir datos al final del mismo. No permite la lectura.
a+ Igual que el anterior, pero permitiendo la lectura.
r Abre el fichero sólo para lectura. No permite la escritura de datos.
r+ Abre el fichero para lectura, permitiendo la escritura de datos que se grabarán al principio del contenido actual.
w Abre un fichero para escribir datos que sustituirán a los que ya pueda haber. No permite la lectura.
w+ Igual que el anterior, pero permitiendo la lectura.
x Creación y apertura para sólo escritura. Coloca el puntero del fichero al principio del mismo. Si el fichero ya existe, la llamada a fopen() fallará devolviendo FALSE y generando un error de nivel E_WARNING. Si el fichero no exite se intenta crear.
x+ Igual que el anterior, pero permitiendo la lectura.
c Abrir el fichero para sólo escritura. Si el fichero no existe, se crea. Si existe no es truncado (a diferencia de w), ni la llamada a esta función falla (como en el caso con x). El puntero al fichero se posiciona en el principio del fichero.
c+ Igual que el anterior, pero permitiendo la lectura.
b Abre un fichero binario.

En los modos a, a+, w y w+ se intenta abrir el fichero. Si no existe, se crea en ese momento. En los modos r y r+ se intenta abrir el fichero.

El modificador b se emplea, adicionalmente a alguno de los anteriores, para abrir ficheros binarios. Por ejemplo, un archivo que, en lugar de texto, contiene una imagen. Cuando se trabaja en una plataforma Unix (o Linux, Solaris, etc.) no existe diferencia entre abrir un fichero de texto o uno binario. Windows, en cambio, sí reconoce esa diferencia. Ten en cuenta que, aunque estés trabajando en tu equipo en entorno Windows, la mayoría de los servidores profesionales corren bajo Linux. Las razones para esto son varias. En primer lugar, no hay que pagar una licencia. Además Linux es abierto, se puede modificar y recompilar según las necesidades del servicio. Microsoft, en cambio, vende sus licencias de uso de Windows “tal como es”. Si no cubre una necesidad específica, no se puede hacer nada. Cuando escribas tu sitio para Internet, y una vez lo hayas probado y te funcione correctamente, seguro que contratarás el alojamiento en un servidor profesional. Si bien la mayoría de las compañías ofrecen plataformas Linux y Windows, estas últimas suelen ser más caras, ya que al coste propio del servicio hay que añadirle un prorrateo por la licencia que se le paga a Microsoft. Ésto no debe preocuparte. Como el trabajo con tus scripts es llevado a cabo por el intérprete PHP, éstos funcionarán bien en cualquier servidor local o remoto.

Volviendo al tema de la apertura de ficheros, esta es, como te digo, la primera operación que debe llevar a cabo tu script cuando quieras leer o escribir en un fichero. La sintaxis general de fopen() es la siguiente:

$manejador = fopen($nombreFichero, $modo);

Fíjate en que esta función devuelve un identificador, o manejador (como prefieras), que debe ser asignado a una variable. Este manejador será el que posteriormente se emplee para leer o escribir en el fichero, así como para cerrarlo.

Llegados a este punto quiero hacerle un inciso del que seguramente no oirá hablar mucho. Esta función permite abrir ficheros remotos, es decir, situados en otros servidores. Sin embargo, para ello es necesario que esté activada la directiva allow_url_fopen en el fichero de configuración. Hablaremos de configuración de PHP en un artículo posterior en esta serie. Cuando quieras acceder a ficheros situados en servidores remotos, deberás contar con los permisos adecuados. Evidentemente, por razones de seguridad, uno no puede acceder por las buenas a un fichero que está en otro servidor. Esto es lógico. Si tú pones un fichero en tu servidor no querrás que todo el mundo pueda leerlo y, lo que puede ser más grave, escribir en él a su antojo. En el siguiente artículo de esta serie hablaremos sobre el tema de los permisos.

CERRAR FICHEROS

Cuando hayamos llevado a cabo cualquier operación con un fichero, tanto de lectura como de escritura, es necesario cerrarlo. Para ello recurrimos a la función fclose(), que recibe, como argumento, el manejador que se creó al abrir el fichero. De este modo, podemos tener abiertos varios ficheros en un script, y cerrarlos según vayamos dejando de necesitarlos. Recuerda una cosa. Siempre que abras un fichero deberá cerrarlo cuando termines de trabajar con él. El hecho de dejar un fichero abierto puede acarrear problemas en posteriores accesos e, incluso, la pérdida de información. NUNCA, bajo ningún concepto, olvides cerrar los ficheros que hayas abierto. Quizás, si pruebas a usar ficheros y dejarlos sin cerrar, no te ocurra nada en una ocasión, o en diez, o en cien mil, pero es un problema que estás dejando al azar, y no se hacen planes para la suerte.

Existe otra razón no menos importante para cerrar un fichero que ya no necesites. Un manejador es, en definitiva, un recurso de PHP para la gestión del fichero. Como cualquier recurso, consume memoria. Si no lo necesitamos, lo cerrarmos y eso que ahorramos.

La sintaxis genérica de esta función es la siguiente:

fclose ($manejador);

El manejador es, como te he dicho antes, el que se creó al abrir el fichero.

LEER EN FICHEROS

Ya sabes cómo abrir y cerrar un fichero. Ahora veamos qué podemos hacer desde que se abre hasta que se cierra. Para empezar vamos a considerar la lectura de un fichero. Consideremos un fichero de texto plano, cuyo nombre es, por ejemplo, lecturaSimple.txt. En su interior puede haber cualquier fragmento de texto, una frase, un párrafo de una revista, o lo que sea. Crealo con tu editor de texto plano favorito y así sabrás lo que contiene. Para leer todo el contenido de un fichero, de modo indiscriminado, podemos usar la función fpassthru(). Ésta recibe, como argumento, el manejador con el que se ha abierto el fichero, y vuelca en la salida estándar (la pantalla del navegador) el contenido del mismo. Mira el script lecturaSimpleR.php, listado a continuación:

Carga el script en el navegador para comprobar su resultado. En la página te aparece el contenido del fichero de texto. Observa que el script tiene tres líneas de código, que realizan las tres operaciones básicas que conocemos. La primera línea abre el fichero, la segunda lo lee y la tercera lo cierra. Quiero llamar tu atención sobre algo que hemos comentado, pero que aquí puedes ver claramente por primera vez. La primera línea abre el fichero en modo lectura (r) y crea un manejador de fichero, al que hemos llamado $manejadorFichero1. Este manejador es el que emplean la segunda y tercera línea para leer y cerrar el fichero respectivamente.

La función fpassthru() tiene un uso adicional. Si le asignamos la salida a una variable, nos devuelve el número de caracteres que contiene el fichero. Observa el script listadoConCuentaR.php, que aparece a continuación:

El resultado lo puedes ver en tu navegador.

PHP nos ofrece otras funciones destinadas a la lectura de un fichero. La función fread() permite leer un número determinado de caracteres. Esta función recibe dos argumentos. El primero es, cómo no, el manejador del fichero. El segundo es el número de caracteres que deseamos leer. La función devuelve una parte del fichero, de tantos bytes de longitud como hayamos expresado en el segundo argumento. Este resultado de la función debe ser asignado a una variable para luego poder mostrarlo en la página, o procesarlo del modo que nos resulte conveniente.

Esta función trabaja con un puntero que se posiciona en el fichero, de modo que, al abrirlo, apunta al principio del mismo. Al ejecutarse la función, el puntero se “desplaza” tantos caracteres como se hayan leído. Así pues, si el segundo argumento de la función es, digamos, 10, el puntero quedará posicionado en el carácter 11. Si se vuelve a ejecutar la función, se leerá a partir de ahí, no desde el comienzo, como la primera vez. También puede ocurrir que se llegue al final del fichero. Todos los ficheros tienen una marca llamada EOF (End Of File), que señala esta circunstancia. Si la función fread() debe leer, digamos, 20 caracteres, pero encuentra antes la marca EOF, leerá hasta ese punto.

Esta función se complementa muy bien con rewind(), que recibe, como argumento, el manejador del fichero sobre el que queremos trabajar, y posiciona el puntero de lectura en el primer carácter.

Observa el código leerConReadR.php, listado a continuación:

Prueba el código para ver el resultado en pantalla y observa en las líneas resaltadas cómo hemos hecho uso de las dos funciones: fread() y rewind().

Podemos determinar el tamaño de un fichero mediante la función filesize(), que recibe como argumento el nombre del fichero cuyo tamaño queremos averiguar. Presta atención a esto. A esta función no se le pasa el manejador con el que abrimos el fichero, ya que es operativa, incluso, si no se ha abierto ningún fichero. Se le pasa el nombre (y, en su caso, la ruta) del fichero que nos interesa. Mediante el uso de esta función podríamos leer un fichero completo usando fread(). Mira el código del script leerConSizeR.php:

Observa, en la línea resaltada, cómo hemos usado la función filesize() para determinar el tamaño del fichero y leerlo en un solo bloque.

En PHP contamos con otra función de lectura que permite recuperar el contenido de un fichero en bloques de un solo carácter: se trata de fgetc(), que recibe, como argumento, el manejador del fichero del cual queremos leer. Mira el código del script leerCaracterR.php, donde se ha usado esta función, en combinación con filesize() para leer todo el contenido de un fichero, carácter a carácter.

Al ejecutar este código se encuentra con una página que se corresponde con los resultados anteriores. Observa, en el bloque resaltado, cómo hemos hecho uso de un bucle, basado en el tamaño del fichero, para recuperar su contenido, carácter a carácter.

Cuando se lee un fichero, éste no tiene que tener, necesariamente, la extensión .txt, como hemos venido haciendo hasta ahora. Puedes programar tu script para que lea, por ejemplo, el listado de una página HTML, que también es un fichero de texto, pero que tiene la extensión .htm. En ese caso, se cargará la página leída en el navegador como si la hubiéramos llamado directamente. Puedes ver un ejemplo de esto en leerHTML.php, cuyo listado aparece a continuación:

Como ves, se trata de leer una página HTML. Crea cualquier documento HTML, ejecuta el script y verás tu documento HTML en el navegador cómo si lo hubieras cargado directamente.

En PHP contamos con otra función de lectura de ficheros destinada a leer cadenas completas, llamada fgets(). Ésta recibe dos argumentos separados por comas. El primero es, lógicamente, el manejador con el que se ha abierto el fichero. El segundo es el número de bytes que queremos leer, más uno. Así, si queremos leer 10 caracteres, como segundo parámetro pondremos 11. Dicho así, suena muy similar a fread(). Sin embargo, hay algunas diferencias. El segundo argumento es opcional. Si no se incluye se considerará 1.024 por defecto. Además, si antes de leer los caracteres especificados aparece un salto de línea, la lectura termina en ese punto. Esta función trabaja muy bien en combinación con feof(), que se emplea para detectar cuándo se ha llegado al final del fichero. Ésta recibe como argumento el manejador del fichero y devuelve un valor lógico, true o false, dependiendo de que se haya alcanzado o no el final. Puede ver el uso de estas dos funciones en el script leerCadenas.php:

Mira, en las líneas resaltadas, cómo hemos empleado las dos funciones que acabamos de conocer.

Existe otra función, similar a fgets(), que es fgetss(). Su sintaxis es la misma que la de la anterior, pero elimina TODAS las etiquetas de HTML, PHP y JavaScript. Observe el listado leerSinEtiquetas.php:

La única diferencia con el código anterior está en la línea resaltada. Como ves, se han suprimido todas las etiquetas HTML, quedando sólo las cadenas de texto que hay en el fichero, sin más.

Además de las funciones ya vistas existe una función de lectura de ficheros que resulta muy práctica. Se trata de file(). Como argumento recibe un nombre de fichero que no tiene por qué estar abierto previamente, y devuelve una matriz indexada en la que cada elemento tiene una línea del fichero. Observa el listado leerParaMatriz.php:

Al ejecutarlo verás en la página las líneas de texto del fichero multiLinea.txt como elementos de una matriz. Posteriormente puedes tratar la susodicha matriz y/o sus elementos como cualquier otra, con las funciones que ya conoces.

Cuando se lleva a cabo la lectura de un fichero es necesario, muy a menudo, detectar la posición del puntero de lectura. Ya aprendimos, al ver la función fread() lo que es este puntero. Y también hemos aprendido a “rebobinarlo” al principio del fichero con rewind(). Además, el puntero es capaz de indicarnos si ha alcanzado el final del fichero mediante la función feof(). Existe una función específica para obtener la posición del puntero en cualquier momento de la lectura. Se trata de  ftell(), que recibe como argumento el manejador con el que se abrió el fichero. En el siguiente código, llamado verElPuntero.php vemos cómo funciona:

Quiero llamar tu atención sobre la línea que aparece resaltada, donde se usa la función ftell() para determinar la posición del puntero de lectura. Cuando ejecutes este script verás cómo se muestra en la página el recorrido del puntero, junto con el carácter que tiene el fichero en cada posición.

Quiero que te fijes en una cosa. En este código hemos hecho la identificación de la posición del puntero después de leer un carácter, dentro del bucle. Fíjate en la disposición de las líneas de código, en cada iteración del bucle: primero leemos un carácter (con lo que se produce un desplazamiento del puntero), y luego vemos su posición. Al ejecutar el código, la primera posición que aparece corresponde al número 1. Esto es así porque, en realidad, el primer carácter es el 0. Si el uso de ftell() estuviera antes de la lectura de cada carácter, las posiciones aparecerían numeradas desde 0, en lugar de hacerlo desde 1.

Y, ahora que ya sabes determinar la posición del puntero, veamos de qué modo lo llevaremos a donde nos pueda interesar. Para desplazar el puntero ya conoces la función rewind(), que lo posiciona al principio del fichero. Sin embargo, en ocasiones querremos llevarlo a otra posición diferente. Para ello, contamos con la función fseek(). Ésta recibe dos argumentos. El primero es el manejador del fichero sobre el que estamos trabajando, y el segundo es la posición a la que queremos desplazar el puntero. Esta posición se toma con respecto al inicio del fichero. Observa el script moverPuntero.php, listado a continuación:

Vea en la línea resaltada que desplazamos el puntero hasta el cuarto carácter del fichero, que es el número tres ya que, como hemos visto anteriormente, los caracteres empiezan a numerarse desde 0.

En la actualidad esta función puede recibir un tercer argumento, opcional, que indica desde dónde va a hacerse el desplazamiento. Como hemos visto, por defecto se hace desde el principio del fichero. Este argumento puede ser una de las tres constantes siguientes:

  • SEEK_SET. Efectúa el desplazamiento desde el inicio del fichero. Es el valor que se asume por defecto, por lo que se puede omitir.
  • SEEK_CUR. Efectúa el desplazamiento desde la posición actual del puntero. Si el segundo argumento es positivo, desplaza el puntero hacia delante. Si es negativo, lo desplaza hacia atrás.
  • SEEK_END. Efectúa el desplazamiento desde el final del fichero hacia atrás. En este caso el segundo argumento debe ser negativo.

Para ver un ejemplo del uso de este tercer parámetro mira el listado del script fseek3argumentos.php, que aparece a continuación:

En la línea resaltada ves el uso completo de esta función.

ESCRIBIR EN FICHEROS

El proceso de escribir en un fichero es, paradójicamente, más simple que el de lectura, desde el punto de vista de las funciones destinadas a ello. Lo primero que debemos tener en cuenta cuando vayamos a escribir algo en un fichero es que debemos abrirlo usando el modo a o el modo w, en lugar del modo r. Si, además, prevemos que pueda ser necesario efectuar alguna lectura en el fichero, usaremos los modos a+w+, que permiten realizar ambas operaciones sin necesidad de cerrar y volver a abrir.

Para escribir en un fichero, empleamos la función fwrite(), que recibe tres argumentos. El primero es el manejador con el que se ha abierto el fichero. El segundo es el contenido que queremos escribir. El tercer parámetro es opcional. Se trata de un límite (un valor numérico) referente a la cantidad máxima de caracteres que se escribirán en la operación en curso, de modo que, si el segundo argumento tiene mayor longitud que la permitida por el tercero, sólo se grabará parte del nuevo contenido. Para comprobar la operativa de esta función vamos a empezar con un código que la emplea con los dos primeros parámetros, sin incluir el tercero. Se llama escrituraCompleta.php, y aparece listado a continuación:

Observa, en la línea resaltada, el uso de fwrite(). En este ejemplo hemos aprovechado la cualidad que tienen muchas funciones de PHP de devolver un valor true o false para comprobar si se ha podido llevar a cabo la operación en curso. Como el fichero donde se escribe la cadena, llamado escrituraCompleta.txt, no existe, por defecto, en la carpeta en la que estamos trabajando, el intérprete del lenguaje se encarga de crearlo. Recuerda que, si estuviéramos trabajando en un servidor remoto (como se trabaja en Internet) el archivo de texto se crearía en dicho servidor, no en el lado del cliente.

Una vez hayas ejecutado este script comprobarás cómo se ha creado el archivo de texto. Ábrelo con cualquier editor y verás que su contenido es la cadena que hemos establecido como segundo parámetro de la función.

Ahora ejecuta el código escrituraLimitada.php. Es muy similar al anterior. La única diferencia (aparte del nombre del fichero de texto) es el uso de fwrite() con el tercer argumento, limitando la operación de escritura a seis caracteres, así:

if (@fwrite($manejador, $cadena, 6)) {

Observa el uso de este parámetro. Si ahora abres con un editor de texto el fichero escrituraLimitada.txt verás que el contenido tiene sólo los seis primeros caracteres de la cadena que se quiso grabar, incluyendo el espacio en blanco.

Existe otra función para escritura en ficheros. Su nombre es fputs() y es lo que se conoce como un alias de fwrite(). Esto significa que tiene la misma sintaxis y funciona exactamente igual, por lo que puede usar cualquiera de las dos funciones indistintamente.

ELIMINAR FICHEROS

En ocasiones es necesario que se borren determinados ficheros en el servidor. Probablemente sean archivos que ya no van a utilizarse más, y que están ocupando un espacio que podemos necesitar para otro uso. En ese caso, empleamos la función unlink(), que recibe como argumento el nombre del archivo a eliminar. Para ejecutar esta función es necesario que el fichero no esté abierto. Si lo está, no se podrá llevar a cabo la eliminación. Si el fichero no existe, tampoco se podrá llevar a cabo su borrado, como es lógico. Observa un ejemplo de uso en el código del script eliminarFichero.php, listado a continuación:

En la línea resaltada vemos cómo se usa unlink(). Cuando cargues este script en el navegador, verás que se elimina el fichero. Un mensaje te informa de ello en la página, tal como se ve en el código. Si vuelves a cargarlo, te saldrá el otro mensaje: el que le informa de que no se ha podido eliminar el fichero. Lógico, ya se eliminó en la primera ejecución, así que ya no existe y, por lo tanto, no puede eliminarse de nuevo. Recuerda que cuando se elimina un fichero se pierde de forma definitiva e irreversible. En el servidor no existe papelera de reciclaje, ni nada así. Ya no podrás recuperarlo de ningún modo.

COPIAR FICHEROS

Un fichero se puede copiar, en la misma ruta en la que está o en otra diferente, desde un script PHP mediante el uso de la función copy(). Esta función recibe dos argumentos. El primero es el nombre del fichero que queremos copiar y el segundo es el nombre que tendrá la copia. Si la ruta de alguno de ellos es diferente de aquélla en la que se ejecuta el script, también deberemos especificarla, como es lógico. Observa el listado copiaFichero.php, a continuación:

Este script está diseñado para hacer una copia de uno de los ficheros de texto empleados en las pruebas de lectura. Si todo ha ido correctamente, la página debe informarle de que el archivo se ha copiado, y en la carpeta de este capítulo debe aparecer ahora el archivo de la copia, con el nombre especificado, y con el mismo contenido que el archivo original. Como es lógico, para que esto funcione el archivo original debe existir en la ruta especificada. Además, en la ruta de destino debes tener permisos para escribir. Mira el próximo artículo al respecto.

RENOMBRAR FICHEROS

PHP nos permite cambiar el nombre de un archivo desde un script. Para ello recurrimos a la función rename(). Ésta debe recibir dos argumentos. El primero es el nombre que tiene el fichero antes de renombrarlo. El segundo parámetro es el nuevo nombre que le queremos dar. Esta función se puede usar, también, para cambiar la ubicación de un archivo (lo que se conoce como mover un archivo), simplemente especificando una ruta diferente en el nuevo nombre. En las anteriores versiones de PHP no se podía usar para mover un archivo, en entornos Unix, si el destino no pertenecía al mismo disco que el origen, pero esto fue resueslto hace tiempo.

Supongamos el siguiente fragmento de código:

$origen = "fichero.txt";
$destino = "nuevoFichero.txt";
@rename ($origen, $destino);

Esto cambiaría el nombre del archivo fichero.txt por nuevoFichero.txt, dejándolo en la misma ruta. Ahora observe lo siguiente:

$origen = "fichero.txt";
$destino = "otroDirectorio/fichero.txt";
@rename ($origen, $destino);

Este fragmento movería el archivo fichero.txt a un directorio llamado otroDirectorio que se encuentra dentro del actual, conservando el nombre original del archivo.

Por supuesto, para que estas operaciones se puedan llevar a cabo es preciso que el archivo exista con el nombre original en la ruta especificada.

ATENCION. Para realizar operaciones de lectura en los ficheros es necesario que el directorio en que se encuentran estos, así como los propios ficheros, cuenten con permiso de lectura. Por supuesto, lo mismo ocurre con las operaciones que implican algún tipo de escritura o modificación (escibir en el fichero, cambiarle el nombre, copiarlo o eliminarlo). Tanto el fichero en sí, cómo el directorio dónde se encuentra, o dónde queremos alojarlo, deberán tener permisos de escritura.

La siempre peliaguda cuestión de los permisos se comentará en el siguiente artículo.

PROPIEDADES DE LOS FICHEROS

No siempre se puede leer un fichero. A veces éste no existe, o puede que no tengamos los permisos adecuados (cómo hemos dicho, hablaremos de los permisos en el siguiente artículo, ya no te lo digo más, palabrita). Lo mismo puede ocurrir con las operaciones de escritura o de eliminación. Antes de intentar llevar a cabo alguna de estas maniobras es interesante saber si se podrá efectuar. PHP nos proporciona funciones muy útiles.

Empezaremos por conocer la función file_exists(). Como argumento recibe un nombre de fichero (incluyendo la ruta, si procede) y devuelve un valor lógico, que será true si el fichero existe en la ruta especificada, o false en caso contrario.

La función is_readable() recibe como argumento un nombre de fichero (y la ruta, en su caso) y comprueba si el fichero se puede leer. En ese caso devuelve un valor true, y un valor false si el fichero no existe o no es legible.

Otra función a la que deberemos recurrir es is_writeable(). Recibe un nombre de fichero (con su ruta, si procede) y devuelve un valor true si el fichero nos permite escribir en él. Si el fichero no existe o no es escribible, obtendremos un valor false. Un fichero puede no ser escribible si está almacenado en un soporte que no admita la re-escritura, como un CD o similar.

La función is_executable() recibe un nombre de fichero (y su ruta) y devuelve un valor true si el fichero es ejecutable. Si el fichero no existe o no es ejecutable, devuelve un valor false. Esta función tradicionalmente disponible para usuarios de plataformas Unix, se incorporó para Windows en la versión 5 de PHP.

La función is_file() determina si el nombre pasado como argumento es un fichero. En ese caso devuelve un valor true. Si no existe o no es un fichero, devuelve el valor false.

La función is_dir() determina si el nombre pasado como argumento es un directorio. En ese caso devuelve un valor true. Si no existe o no es un directorio, devuelve el valor false.

La función is_link() determina si el nombre pasado como argumento es un enlace simbólico. En ese caso devuelve un valor true. Si no existe o no es un enlace simbólico devuelve el valor false. Esta función, y el concepto de enlace simbólico, pertenecen a los entornos Unix. En entornos Windows no existen enlaces simbólicos. El concepto equivalente serían los accesos directos, pero PHP no los reconoce como enlaces, ni como nada. Por tanto, en entornos Windows esta función carece de sentido.

Para ver cómo operan estas funciones vamos a emplear el listado comprobarPropiedades.htm, que aparece a continuación:

Aparentemente no tiene nada de especial. Sólo es un formulario con un campo de archivo en el que el usuario selecciona un fichero de su disco duro. Sin embargo, fíjate en la línea que aparece resaltada, donde se abre el formulario. No hemos incluido el atributo enctype="multipart/form-data", preceptivo en los formularios que incluyen campos de archivos. Como sabes, este atributo permite que, al mandar el formulario, se envíe el archivo seleccionado. Al no haberlo incluido, sólo se envía el nombre (con la ruta) de dicho archivo, que es, precisamente, lo que necesitamos en este caso. Este nombre se envía al script comprobarPropiedades.php, listado a continuación:

Observa que lo único que hacemos es comprobar cada una de las propiedades que hemos descrito antes y mostrar en la página el mensaje adecuado en cada caso. Puedes probar estas páginas con distintos archivos y ver los resultados.

ATENCIÓN. Por supuesto, esto funciona porque tu servidor está en la misma máquina física que tu navegador y todos tus ficheros. Evisdentemente, si quisiéramos operar sobre un servidor remoto, tendríamos que enviar el fichero en sí (no sólo su nombre) y almacenarlo en el disco antes de poder comprobar nada sobre él.

DIRECTORIOS

Como ya sabes, los ficheros en el disco duro se organizan en una estructura compartimentada, dentro de unos contenedores adecuados. En entornos Windows estos contenedores se llaman carpetas. En entornos Unix, Linux, etc., se llaman directorios. El nombre cambia, pero el concepto es similar (salvando, lógicamente, las diferencias de ambos sistemas de archivos).

Por supuesto, cuando trabajas de modo remoto contra un servidor, el sistema de organización persiste. Por ejemplo, si tu sitio incluye un formulario para que el usuario envíe fotografías que luego se publicarán en alguna de tus páginas, lo normal es que éstas se almacenen en un directorio específico. Los archivos de código (HTML, JS, PHP, etc.) también tendrán su propio directorio, y así, sucesivamente. Los directorios tienen cierta funcionalidad implícita, es decir, se pueden crear nuevos directorios, se puede cambiar el directorio por defecto y se pueden eliminar directorios. PHP nos proporciona las funciones adecuadas para ello, que vamos a conocer en esta sección.

Cuando trabajamos con un directorio, en él se pueden encontrar una serie de ficheros y otros directorios, dando lugar a la típica estructura en árbol de cualquier sistema de almacenamiento actual. Entre los elementos que hay en un directorio encontraremos dos específicos: el punto (.), que se refiere al directorio actual y el punto-punto (..), que se refiere al directorio padre del actual. Por supuesto, este último no existe en el directorio raíz de la partición.

Tu ya sabes referirte a los directorios de una partición. El concepto de rutas absolutas y rutas relativas lo conoces desde que empezaste a manejar enlaces en HTML. Pero hay un punto sobre el que, llegado este momento, quiero llamar tu atención, a pesar de que ya lo hemos usado de pasada. Sabes que en un entorno Windows puede usar el slash (/) o el contraslash (\) indistintamente para separar los nombres de los directorios en una ruta. Sin embargo, en entornos Unix-Linux sólo se reconoce el slash, por lo que nosotros siempre emplearemos este guarismo para garantizar la portabilidad de aplicaciones.

MANEJO BÁSICO DE DIRECTORIOS

Existen tres operaciones básicas que podemos realizar con los directorios:

  • Crear un nuevo directorio.
  • Cambiar el directorio actual (por defecto).
  • Eliminar un directorio.

PHP nos proporciona tres funciones de muy sencillo uso para esto. La primera es mkdir(), que permite crear un nuevo directorio. Esta función recibe dos argumentos, separados por comas. El primero es el nombre del directorio que queremos crear y el segundo representa los permisos con los que queremos crear dicho directorio. Respecto a los permisos de los directorios, es válido todo lo que hemos aprendido sobre permisos en la parte de ficheros, incluyendo el uso de las funciones que hemos estudiado. Supongamos que queremos crear, dentro del directorio actual, uno con el nombre carpetaDeImagenes y con el máximo de permisos para los tres niveles de usuarios. Usaremos la función mkdir() como sigue:

mkdir ("carpetaDeImagenes", 0777);

Ahora suponte que quieres crear un directorio llamado otraCarpeta, directamente en el directorio raíz de la partición activa (normalmente, C:/, en entornos Windows). Usaremos la siguiente instrucción:

mkdir ("C:/otraCarpeta", 0777);

Para cambiar el directorio actual usamos la función chdir(). Ésta recibe un argumento único, que es el nombre de la carpeta a la que queremos referirnos. Suponga que queremos acceder al directorio llamado carpetaDeImagenes que hemos creado anteriormente. Usaremos la siguiente instrucción:

chdir ("carpetaDeImagenes");

Ahora supón que queremos acceder a un directorio llamado carpetaDeSonidos, que se encuentra en una rama paralela a la ruta por defecto, es decir, “cuelga” del padre del directorio actual. Usaremos lo siguiente:

chdir ("../carpetaDeSonidos");

Si queremos eliminar un directorio recurrimos a la función rmdir(), que recibe como argumento el nombre del directorio que deseamos que desaparezca. Para borrar un directorio es necesario que esté vacío (sin ficheros u otras carpetas en su interior) y que tengamos permiso de escritura sobre él. Supongamos que, habiendo vuelto al directorio de nuestros ejemplos anteriores, deseas eliminar carpetaDeImagenes. Usarías una instrucción como la siguiente:

rmdir ("carpetaDeImagenes");

Respecto a la eliminación de un directorio te digo lo mismo que respecto a un fichero: es definitiva e irreversible, así que píensalo dos veces.

Cada una de las tres funciones que acabamos de ver devuelve un valor true si ha podido llevarse a cabo correctamente, y un valor false en caso contrario.

Existe una función adicional, menos conocida, que nos permite recuperar el nombre del directorio actual. Se llama getcwd(). Esta función no recibe ningún argumento.

Y ahora que ya sabemos crear directorios, cambiar el directorio activo y eliminar aquéllos que ya no necesitemos, tendremos que poder hacer “algo”, con los directorios. Por supuesto, siempre podremos grabar en ellos los ficheros que lleguen a través de formularios, mediante la función move_uploaded_file(), que conocimos en un artículo anterior. O podremos copiar, renombrar o eliminar archivos, o incluso crearlos y leerlos, mediante las funciones que hemos aprendido en este mismo artículo.

Sin embargo, hay cuatro operaciones básicas que aún no conocemos, destinadas a “ver” el contenido de un directorio. En efecto, en ocasiones es necesario determinar qué ficheros y sub-directorios contiene una carpeta. Para ello, debemos empezar por “abrirla”, mediante la función opendir(). El argumento que recibe es el nombre del directorio cuyo contenido queremos leer. Esta función devuelve un manejador de directorio, de modo similar a lo que ocurre cuando abrimos un fichero.

Una vez abierto el directorio recurrimos a la función readdir() para leer su contenido. Como argumento le pasamos el manejador que obtuvimos al abrirlo y nos muestra (en seguida veremos cómo) el contenido del directorio.

Cuando se lee el contenido de un directorio mediante la función anterior, se está moviendo internamente un puntero, de modo análogo a como ocurre con los ficheros. Si queremos situarlo al principio del directorio, usaremos la función rewinddir(), que recibe, como argumento, el manejador del directorio.

Por último, cuando hayamos terminado de leer el contenido de un directorio, lo cerraremos con closedir(). Esta función recibe, como argumento, el manejador del directorio.

Supón que deseas leer el contenido de la carpeta principal en la partición activa. Para este ejemplo supondremos que estamos trabajando en un entorno Windows y que nuestra partición se llama C:/. El siguiente script, de nombre mostrarC.php, mostraría su contenido:

Cuando ejecutes este código verás en tu página una lista de los directorios y archivos que tienes en tu disco duro. Sin embargo, es una forma bastante limitada de explorar el disco. Podemos mejorarla mucho. Por ejemplo, un usuario siempre agradece una interfaz gráfica cómoda y manejable. Observa el listado del script que aparece a continuación, y que hemos llamado gestionarDirectorios.php:

Lógicamente, el resultado que te aparezca a ti será diferente, dado que no tienes los mismos directorios y ficheros que yo. Observa los dos tipos de icono diferentes que aparecen a la izquierda de cada elemento y que indican si el mismo es una carpeta u otro elemento (genéricamente, un fichero). Los iconos que se refieren a un directorio son, además, un enlace para abrirlo. Pulse sobre alguno de ellos y verás cómo la página se recarga, mostrando el contenido del mismo. Si, una vez dentro de una carpeta pulsas sobre el elemento .. verás que vuelves al directorio padre correspondiente. En los ficheros no he montado enlaces para su apertura por dos razones. La primera, y más evidente, es que sobre los ficheros ya hemos hablado y se escapa del objetivo de este ejercicio en concreto. La segunda es que abrir indiscriminadamente ficheros del disco duro, sin saber cuáles y de qué modo, puede acarrearnos problemas.

Los iconos no están incluidos en el ejercicio. Te los dejo aquí para que te los copies archivo directorio

Estudia el código, que emplea funciones que ya conocemos perfectamente, así como recursos de HTML y JavaScript. Presta especial atención a los comentarios que he incluido al efecto, ya que le aportan gran valor didáctico.

Un comentario acerca de la lectura de directorios. PHP te permite, al igual que ocurre con los ficheros, la apertura remota, es decir, en otro equipo. Desde la versión 5 se ha incorporado la envoltura URL ftp://. Esto significa que podemos abrir directorios remotos para trabajar con ellos mediante el protocolo de transferencia de archivos. Hablaremos de la gestión remota de recursos más adelante, en esta misma serie de artículos.

.

     

Un comentario:

  1. Pingback: PHP-TUT-20 Gestión de imágenes (I) » eldesvandejose.com

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *