Operaciones con archivos
Proporciona funciones de alto nivel sobre Archivos y directorios.
Funciones
bool_t | hfile_dir (...) |
bool_t | hfile_dir_create (...) |
bool_t | hfile_dir_destroy (...) |
ArrSt(DirEntry)* | hfile_dir_list (...) |
void | hfile_dir_entry_remove (...) |
Date | hfile_date (...) |
bool_t | hfile_dir_sync (...) |
bool_t | hfile_exists (...) |
bool_t | hfile_is_uptodate (...) |
bool_t | hfile_copy (...) |
Buffer* | hfile_buffer (...) |
String* | hfile_string (...) |
Stream* | hfile_stream (...) |
bool_t | hfile_from_string (...) |
bool_t | hfile_from_data (...) |
bool_t | hfile_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.
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); |
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 |
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 |
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 |
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 |
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 |
remove_in_dest | Si |
except | Lista de nombres de archivo/directorio que permanecerán intactos en |
except_size | Tamaño del array |
error | Código de error si la función falla. Puede ser |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
hiddens | Si es |
error | Código de error si la función falla. Puede ser |
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.