SDK Multiplataforma en C logo

SDK Multiplataforma en C

Operaciones con archivos

❮ Anterior
Siguiente ❯

Proporciona funciones de alto nivel sobre Archivos y directorios.


Funciones

bool_thfile_dir (...)
bool_thfile_dir_create (...)
bool_thfile_dir_destroy (...)
ArrSt(DirEntry)*hfile_dir_list (...)
voidhfile_dir_entry_remove (...)
Datehfile_date (...)
bool_thfile_dir_sync (...)
bool_thfile_exists (...)
bool_thfile_is_uptodate (...)
bool_thfile_copy (...)
Buffer*hfile_buffer (...)
String*hfile_string (...)
Stream*hfile_stream (...)
bool_thfile_from_string (...)
bool_thfile_from_data (...)
bool_thfile_dir_loop (...)
String*hfile_appdata (...)
String*hfile_home_dir (...)

Si bien en Archivos y directorios ya vimos como acceder al sistema de ficheros a bajo nivel, en ocasiones se hacen necesarias ciertas operaciones de alto nivel sobre los datos en disco. El mero hecho de borrar completamente un directorio lleva asociadas muchas operaciones individuales de bajo nivel. La librería Core, por medio de <hfile.h> provee de ciertas utilidades que nos pueden simplificar la vida en determinados momentos.

  • Utiliza hfile_dir_create para crear un directorio, creando también sus predecesores si no existieran.
  • Utiliza hfile_dir_destroy para eliminar un directorio y todo su contenido de forma recursiva.
  • Utiliza hfile_dir_sync para sincronizar el contenido de dos directorios. Algo parecido al rsync de Unix.
  • Utiliza hfile_dir_loop para recorrer un directorio en profundidad (Listado 1).
  • Utiliza hfile_buffer para cargar en memoria el contenido de un archivo.

Listado 1: Uso de hfile_dir_loop para recorrer un directorio de tres niveles.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
typedef struct _query_t Query;

static void i_OnEntry(Query *query, Event *e)
{
    const EvFileDir *p = event_params(e, EvFileDir);

    // First level (year)
    if (p->depth == 0)
    {
        // The entry is a directory
        if (event_type(e) == ekEENTRY)
        {
            bool_t *enter = event_result(e, bool_t);
            int16_t year = str_to_i16(p->filename, 10, NULL);

            // The loop enter in this subdir (depth 1)
            if (i_process_year(query, year) == TRUE)
                *enter = TRUE;
            else
                *enter = FALSE;
        }
    }
    // Second level (month)
    else if (p->depth == 1)
    {
        // The entry is a directory
        if (event_type(e) == ekEENTRY)
        {
            bool_t *enter = event_result(e, bool_t);
            uint8_t month = str_to_u8(p->filename, 10, NULL);

            // The loop enter in this subdir (depth 2)
            if (i_process_month(query, month) == TRUE)
                *enter = TRUE;
            else
                *enter = FALSE;
        }
    }
    // Third level (files)
    else if (p->depth == 2)
    {
        // The entry is a file
        if (event_type(e) == ekEFILE)
            i_process_file(query, p->pathname);
    }
}

/*---------------------------------------------------------------------------*/

Query query = i_init_query(&query);

hfile_dir_loop("main_path", listener(&query, i_OnEntry, Query), TRUE, FALSE, NULL);
Estructura de directorios y archivos.
Figura 1: Representación del directorio de (Listado 1).
❮ Anterior
Siguiente ❯

hfile_dir ()

Comprueba si la ruta es un directorio.

bool_t
hfile_dir(const char_t *pathname);
pathname

Nombre de la ruta a comprobar. Filename y pathname.

Retorna

TRUE si pathname es un directorio. Si no existe o es un archivo FALSE.


hfile_dir_create ()

Crea todos los subdirectorios intermedios de una ruta.

bool_t
hfile_dir_create(const char_t *pathname,
                 ferror_t *error);
1
2
3
// C:\dir1 doesn't exist.
bool_t ok = hfile_dir_create("C:\dir1\dir2\dir3\dir4\dir5");
ok = TRUE
pathname

Nombre de la ruta a crear. Filename y pathname.

error

Código de error si la función falla. Puede ser NULL.

Retorna

TRUE si la ruta completa ha sido creada, de lo contrario FALSE.


hfile_dir_destroy ()

Destruye recursivamente un directorio y todo su contenido.

bool_t
hfile_dir_destroy(const char_t *pathname,
                  ferror_t *error);
pathname

Ruta del directorio a destruir. Filename y pathname.

error

Código de error si la función falla. Puede ser NULL.

Retorna

TRUE si el directorio ha sido destruido, o FALSE si ha habido algún error.


hfile_dir_list ()

Obtiene una lista del contenido de un directorio.

ArrSt(DirEntry)*
hfile_dir_list(const char_t *pathname,
               ferror_t *error);
pathname

Ruta del directorio a listar. Filename y pathname.

error

Código de error si la función falla. Puede ser NULL.

Retorna

Array de DirEntry con el contenido. Debe ser destruido con arrst_destroy(&array, hfile_dir_entry_remove, DirEntry) cuando ya no sea necesario.


hfile_dir_entry_remove ()

Libera la memoria de un elemento del listado del directorio.

void
hfile_dir_entry_remove(DirEntry *entry);
entry

Elemento.

Observaciones

Ver hfile_dir_list.


hfile_date ()

Obtiene la fecha de modificación más reciente de un archivo o directorio.

Date
hfile_date(const char_t *pathname,
           const bool_t recursive);
pathname

Ruta al archivo o directorio. Filename y pathname.

recursive

Si pathname es un directorio, indica si se realiza una exploración en profundidad por los subdirectorios.

Retorna

La fecha de modificación. Si pathname no existe kDATE_NULL.

Observaciones

Si pathname es un directorio, se considerarán las fechas de modificación de los archivos también, no solo del propio directorio.


hfile_dir_sync ()

Sincroniza el contenido de dos directorios.

bool_t
hfile_dir_sync(const char_t *src,
               const char_t *dest,
               const bool_t recursive,
               const bool_t remove_in_dest,
               const char_t **except,
               const uint32_t except_size,
               ferror_t *error);
src

Directorio origen.

dest

Directorio destino.

recursive

Si TRUE procesa recursivamente los subdirectorios.

remove_in_dest

Si TRUE elimina en dest aquellos archivos/directorios que no estén en src.

except

Lista de nombres de archivo/directorio que permanecerán intactos en dest.

except_size

Tamaño del array except.

error

Código de error si la función falla. Puede ser NULL.

Retorna

TRUE si todo ha ido bien, FALSE si ha habido algún error.

Observaciones

Si un archivo está en src y no en dest, se copia en dest. Si un archivo es más reciente en src también se copia en dest. Si un archivo existe en dest pero no en src y remove_in_dest es TRUE, se eliminará de dest. Si el archivo existe en except no será tenido en cuenta ni para copiar ni borrar. Si recursive es TRUE se procesarán los subdirectorios de esta forma: Si ambos subdirs existen en src y dest se ejecutará la misma lógica descrita en ambos subdirs. Si el subdir existe en src pero no en dest, se copiará en su totalidad a dest. Si existe en dest y no en src y remove_in_dest es TRUE será eliminado completamente de dest.


hfile_exists ()

Comprueba si pathname existe en el sistema de archivos.

bool_t
hfile_exists(const char_t *pathname,
             file_type_t *file_type);
pathname

Ruta del directorio o archivo a comprobar. Filename y pathname.

file_type

Tipo de archivo. Pueder ser NULL.

Retorna

TRUE si pathname existe, FALSE si no.


hfile_is_uptodate ()

Comprueba si un archivo está actualizado. Considera que dest es una copia o depende de src.

bool_t
hfile_is_uptodate(const char_t *src,
                  const char_t *dest);
src

Pathname del archivo de origen.

dest

Pathname del archivo de destino.

Retorna

TRUE si dest existe y es más reciente que src. De lo contrario FALSE.


hfile_copy ()

Copia un archivo de una ubicación a otra.

bool_t
hfile_copy(const char_t *src,
           const char_t *dest,
           ferror_t *error);
1
2
hfile_copy("/home/john/image.png", "/home/john/images", NULL); // image.png
hfile_copy("/home/john/image.png", "/home/john/images/party.png", NULL); // party.png
src

Pathname del archivo a copiar. Filename y pathname.

dest

Destino de la copia. Si es un directorio tendrá el mismo filename que el origen. De lo contrario, la copia se hará con otro nombre de archivo.

error

Código de error si la función falla. Puede ser NULL.

Retorna

TRUE si la copia se ha realizado con éxito. De lo contrario FALSE.


hfile_buffer ()

Crea un búfer con el contenido de un archivo en disco.

Buffer*
hfile_buffer(const char_t *pathname,
             ferror_t *error);
pathname

Ruta del archivo a cargar.

error

Código de error si la función falla. Puede ser NULL.

Retorna

El búfer con los datos del archivo o NULL si la función falla.

Observaciones

No funciona con archivos de más de 4Gb (32-bits).


hfile_string ()

Crea un string con el contenido de un archivo en disco.

String*
hfile_string(const char_t *pathname,
             ferror_t *error);
pathname

Ruta del archivo a cargar.

error

Código de error si la función falla. Puede ser NULL.

Retorna

El objeto string con los datos del archivo de texto o NULL si la función falla.

Observaciones

No funciona con archivos de más de 4Gb (32-bits).


hfile_stream ()

Crea un Memory stream y lo inicializa con el contenido de un archivo.

Stream*
hfile_stream(const char_t *pathname,
             ferror_t *error);
pathname

Ruta del archivo a cargar.

error

Código de error si la función falla. Puede ser NULL.

Retorna

El stream inicializado con los datos del archivo o NULL si la función falla.

Observaciones

No funciona con archivos de más de 4Gb (32-bits).


hfile_from_string ()

Crea un archivo en disco con el contenido de un Strings.

bool_t
hfile_from_string(const char_t *pathname,
                  const String *str,
                  ferror_t *error);
pathname

Ruta del archivo a guardar.

str

String a guardar en el archivo.

error

Código de error si la función falla. Puede ser NULL.

Retorna

TRUE si el archivo ha sido creado con éxito. En caso contrario FALSE.


hfile_from_data ()

Crea un archivo en disco con el contenido de un bloque genérico de memoria.

bool_t
hfile_from_data(const char_t *pathname,
                const byte_t *data,
                const uint32_t size,
                ferror_t *error);
pathname

Ruta del archivo a guardar.

data

Bloque a guardar en el archivo.

size

Tamaño en bytes del bloque.

error

Código de error si la función falla. Puede ser NULL.

Retorna

TRUE si el archivo ha sido creado con éxito. En caso contrario FALSE.


hfile_dir_loop ()

Recorre todos los archivos de un directorio.

bool_t
hfile_dir_loop(const char_t *pathname,
               Listener *listener,
               const bool_t subdirs,
               const bool_t hiddens,
               ferror_t *error);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
static void i_OnEntry(App *app, Event *event)
{
    uint32_t type = event_type(event);
    const EvFileDir *p = event_params(event, EvFileDir);
    if (type == ekEFILE)
    {
        bstd_printf("File: %s\n", p->pathname);
        // Abort the directory loop
        if (app->more == FALSE)
        {
            bool_t *more = event_result(event, bool_t);
            *more = FALSE;
        }
    }
    else if (type == ekEENTRY)
    {
        if (app->direntry == TRUE)
        {
            bstd_printf("Entering: %s\n", params->pathname);
        }
        else
        {
            bool_t *entry = event_result(event, bool_t);
            *entry = FALSE;
        }
    }
    else if (type == ekEEXIT)
    {
        bstd_printf("Exiting: %s\n", params->pathname);
    }
}

hfile_dir_loop("/home/john/personal", listener(app, i_OnEntry, App), TRUE, FALSE, NULL);
pathname

Ruta del directorio. Filename y pathname.

listener

Función callback que se llamará para cada archivo del directorio.

subdirs

Si es TRUE el bucle procesará los subdirectorios.

hiddens

Si es TRUE se procesarán los archivos ocultos.

error

Código de error si la función falla. Puede ser NULL.

Retorna

TRUE si el recorrido ha sido completado con éxito. FALSE si ha ocurrido algún error.

Observaciones

Para cada archivo, se mandará un evento a listener. Será de tipo ekEFILE para archivos regulares, ekEENTRY cuando detecte en un subdirectorio y ekEEXIT cuando salga del mismo (si el subdirectorio se ha procesado). Los atributos del archivo se envían en el parámetro del evento como una estructura EvFileDir. El recorrido continuará hasta que todos los archivos/subdirectorios hayan sido recorridos o se retorne FALSE en event_result. Esta salida controlada no será considerada error y esta función retornará TRUE.


hfile_appdata ()

Obtiene la ruta completa de un archivo de datos o configuración de la aplicación.

String*
hfile_appdata(const char_t *pathname);
1
2
3
4
5
String *fname = hfile_appdata("gui/preferences.cfg");
fname = "C:\Users\USER\AppData\Roaming\MyApp\gui\preferences.cfg"
(in Windows operating system)
...
Stream *out = stm_to_file(tc(fname), NULL);
pathname

Ruta relativa del archivo.

Retorna

La ruta completa al archivo de configuración.

Observaciones

En muchas ocasiones, las aplicaciones necesitan crear archivos de configuración para recordar preferencias del usuario u otro tipo de datos entre sesiones Home y AppData. Esta función añade una ruta relativa y el nombre del archivo y asegura que todos los directorios intermedios existirán.


hfile_home_dir ()

Obtiene la ruta completa a un archivo en el directorio del usuario (home).

String*
hfile_home_dir(const char_t *path);
path

Ruta relativa a partir del directorio home.

Retorna

Ruta absoluta del archivo.

❮ Anterior
Siguiente ❯