Revista Tecnología

Cómo buscar un archivo en diferentes rutas en C++

Publicado el 22 febrero 2016 por Gaspar Fernández Moreno @gaspar_fm

Cómo buscar archivo diferentes rutasCómo buscar un archivo en diferentes rutas en C++

Es algo muy común, hemos creado un software que necesita ciertos archivos para ejecutarse. El ejemplo más común es el archivo de configuración. Tenemos que cargar la configuración de nuestro programa, pero antes, tenemos que saber dónde está, y hay varias alternativas. Pero podemos utilizar el mismo programa para buscar plantillas, páginas web, archivos de datos, en fin, lo que queramos.

Nota: Estos programas están hechos para Linux, aunque si queremos usarlos en Windows, bastará con cambiar la barra / por \ o tal vez queramos hacer una opción multiplataforma, pero no deberíamos tener que cambiar muchas cosas.

Vamos a implementar la búsqueda de dos maneras:

  • Una búsqueda sencilla, en la que especificamos el archivo y las rutas donde queremos buscar y listo
  • Una búsqueda avanzada en la que especificamos una plantilla en las rutas, luego, en esas rutas se sustituirán las palabras clave por sus reemplazos y se buscará el archivo deseado

Búsqueda sencilla

En el ejemplo de mi archivo de configuración. Éste puede estar en varios sitios:

  • miconfig.xml
  • /etc/miprograma.xml
  • /etc/miprograma/miconfig.xml
  • /var/miprograma/miconfig.xml

Lo que deberíamos hacer sería buscar en todas esas rutas (ordenadas por prioridad) y la primera que contenga el archivo de configuración válido, devolverla. Nuestro programa se encargará ya de abrir el archivo, leerlo, etc, pero eso ya es otro tema.

Aquí os dejo un código de ejemplo:

Lo primero que necesitamos es una función para comprobar la existencia de un archivo, ( file_exists(), aunque si queremos velocidad, lo suyo es utilizar una versión de más bajo nivel, por ejemplo accediendo a stat(), directamente del sistema operativo, pero perdemos portabilidad, tendríamos que implementar una versión para cada sistema en el que trabajáramos (cuando llegue C++17, tal vez podremos utilizar:

o algo parecido.

Tras ello, la función findConfigFile nos devolverá un bool diciendo si ha sido capaz de encontrar el fichero o no, y almacenará la ruta completa del fichero en la variable configFile que le pasamos por referencia. Esta función recorrerá la lista completa de rutas y comprobará la existencia de las mismas, la primera que exista la devolverá, por eso debemos ordenarlas por prioridad.

Rizando el rizo: plantillas de rutas

Pero claro, no siempre es tan fácil, en ocasiones, queremos un método general que nos ayude a encontrar varios archivos en diferentes rutas y, además, que pueda buscar en rutas que no sean fijas, me refiero, sea capaz de buscar en el $ HOME del usuario o que la ruta dependa de un parámetro que conoceremos en tiempo de ejecución (tal vez para buscar los archivos del tema de nuestra aplicación).

Este ejemplo, no valdrá en Windows, por la búsqueda del directorio personal del usuario (si quitamos todo lo relativo al HOME, debería compilar sin problema).

En este caso nuestras rutas serán:

  • miconfig.xml : en el directorio actual, puede ser útil mientras estamos desarrollando la aplicación.
  • $HOME/.miprograma.xml
  • $HOME/.miprograma/config.xml
  • /etc/miprograma.xml
  • /etc/miprograma/miconfig.xml
  • /var/miprograma/miconfig.xml

Por otro lado, el nombre del programa y la extensión del archivo no serán fijos. Con el propósito de hacer un método general para todos nuestros programas (o, tal vez queramos configurar módulos de nuestro programa, ya podemos hacer lo que nos dé la imaginación).

En este caso, al llamar a la función findFile(), le pasamos las rutas donde tiene que buscar y los posibles reemplazos dentro de la cadena ( para reemplazas subcadenas utilizamos algo parecido a esto), de esta forma, dentro de cada ruta se reemplazarán los elementos que se encuentran en el mapa de cadenas (la primera parte es la cadena a buscar y la segunda la cadena por la que sustituimos). Y, aunque las cadenas a buscar dentro del mapa las introducimos normalmente, cuando las busquemos en cada ruta, las buscaremos con delimitadores, en este caso, "file", vendrá como ":file", por ejemplo.

Compilando

Cualquiera de los dos ejemplos, si utilizamos GCC, podemos compilarlos así:

$ g++ ejemplo ejemplo.cpp -std=c++11

En cualquier otro sistema, debemos activar en nuestro IDE la opción C++11.

Foto: Milana Vigerova


Volver a la Portada de Logo Paperblog