La interfaz IFileProvider en .NET Core ya proporciona una abstracción para el sistema de archivos, pero tiene una firma muy sencilla y está diseñada únicamente para leer archivos. Por esta razón, Crono proporciona la interfaz IArchivoSistema, junto con IArchivo y IDirectorio. Sus firmas son más completas y están más alineadas con las clases en System.IO, con las que probablemente estés más familiarizado.
IArchivoSistema también implementa IFileProvider, y tanto IArchivo como IDirectorio implementan IFileInfo. Por lo tanto, puedes considerarlo como una extensión de IFileProvider. Todas las interfaces de E/S de Crono tienen métodos asíncronos que IFileProvider no proporciona. Esto es necesario porque IArchivoSistema también puede representar proveedores de almacenamiento en la nube (como el almacenamiento BLOB de Azure) y virtualizar el almacenamiento de archivos basado en bases de datos.
El sistema de archivos virtual utiliza la barra diagonal (/) como delimitador de rutas y no tiene conceptos de volúmenes o unidades. Todas las rutas se especifican y se devuelven como rutas relativas a la raíz del sistema de archivos virtual. No se admiten rutas absolutas que usen una barra inicial (/), un punto (.) o un retroceso a directorios padres (../).
La implementación predeterminada de IFileProvider es ArchivoSistemaLocal. Busca archivos utilizando el sistema de archivos local del disco. Los métodos asíncronos delegan a los métodos síncronos.
A continuación, se muestran algunos ejemplos básicos:
// Obtener la ruta del directorio actual
var rutaDirActual = System.IO.Directory.GetCurrentDirectory();
var sistemaArchivosLocal = new ArchivoSistemaLocal(rutaDirActual);
// Obtener el directorio "MisPlantillas" (MisPlantillas)
var directorioActual = sistemaArchivosLocal.ObtenerDirectorio("MisPlantillas");
// Obtener una lista de archivos en el directorio "MisPlantillas"
var archivos = directorioActual.EnumerarArchivos();
// Obtener el primer archivo
var primerArchivo = archivos.FirstOrDefault();
// Leer los primeros 20 bytes del archivo
var flujoEntrada = primerArchivo.AbrirLeer();
var buffer = new byte[20];
flujoEntrada.Read(buffer);
flujoEntrada.Dispose();
// Convertir el contenido del buffer a cadena
string primerContenido = System.Text.Encoding.Default.GetString(buffer);
var archivoListadoDir = "Listado_Directorio.txt";
// Verificar si el nombre del archivo es único
var noEsUnico = sistemaArchivosLocal.ComprobarNombreArchivoUnico(archivoListadoDir, out var nombreArchivoUnico)
// Crear una nueva instancia de archivo
var archivo = sistemaArchivosLocal.CrearArchivo(noEsUnico ? nombreArchivoUnico : archivoListadoDir);
// Crear contenido para el archivo
var numeroArchivos = directorioActual.ContarArchivos(profundo: false);
var nombresArchivos = new string[archivos.Count()];
// Listar todos los archivos en el directorio actual
for (var i = 0; i < numeroArchivos; i++)
{
nombresArchivos[i] = archivos.ElementAt(i).Name;
}
var contenido = $"El primer archivo en este directorio comienza con:\n\"{primerContenido}\"\n\n"
+ $"Los {numeroArchivos} archivos incluidos son:\n\n" + nombresArchivos.UnionCadena("\n");
// Escribir el contenido en el archivo
var flujoSalida = archivo.AbrirEscribir();
flujoSalida.Write(contenido.ABytesAscii());
flujoSalida.Dispose();
Adaptadores y Decoradores
ArchivoSistemaExpandido
El ArchivoSistemaExpandido es un decorador que toma un prefijo de ruta y una instancia interna de IArchivoSistema. La ruta raíz del sistema de archivos se amplía utilizando el prefijo especificado.
var raizOrganizacion = new ArchivoSistemaLocal(System.IO.Directory.GetCurrentDirectory());
// Contar todas las plantillas de correo electrónico
var efs = new ArchivoSistemaExpandido("/App_Data/PlantillasCorreoElectronico", raizOrganizacion);
// "en" en realidad se resuelve como "/App_Data/PlantillasCorreoElectronico/en"
var numeroArchivos = efs.ContarArchivos("en");
ArchivoSistemaCompuesto
El ArchivoSistemaCompuesto es un adaptador que busca archivos utilizando una colección de instancias de IArchivoSistema. Dado que implementa la interfaz IArchivoSistema, se puede usar de la misma manera que otros sistemas de archivos.
// Crear el sistema de archivos local desde el directorio actual
var raizAlmacenamiento = new ArchivoSistemaLocal(System.IO.Directory.GetCurrentDirectory());
// Crear un sistema de archivos para el directorio de controladores
var raizControladores = new ArchivoSistemaLocal(
raizAlmacenamiento.ObtenerDirectorio("Controllers").PhysicalPath
);
// Crear un sistema de archivos para el directorio de vistas
var raizVistas = new ArchivoSistemaLocal(
raizAlmacenamiento.ObtenerDirectorio("Views").PhysicalPath
);
// Crear el sistema de archivos compuesto con las rutas de controladores y vistas
var sistemaArchivosCompuesto = new ArchivoSistemaCompuesto(raizControladores, raizVistas);
// Verificar si existe el archivo "VentasController.cs"
var tieneControladorVentas = sistemaArchivosCompuesto.ArchivoExiste("VentasController.cs");
// Verificar si existe el directorio "Ventas"
var tieneDirectorioVistaVentas = sistemaArchivosCompuesto.DirectorioExiste("Ventas");
Utilidades especiales
DirectorioHasheado
El DirectorioHasheado es una utilidad que crea un hash basado en los contenidos de un directorio. Esta herramienta puede cargar y almacenar el código hash para compararlo con estados previos. Los hashes se guardan de manera predeterminada en:
App_Data/Inquilinos/Predeterminado/Hash.
Por defecto, el DirectorioHasheado realiza un escaneo plano del contenido del directorio, pero también se puede configurar para realizar un escaneo profundo (que incluye subdirectorios).
// Crear un sistema de archivos local basado en el directorio actual
var raizAlmacenamiento = new ArchivoSistemaLocal(System.IO.Directory.GetCurrentDirectory());
// Crear un DirectoryHasher para el directorio "Controllers", con escaneo profundo
var hasher = raizAlmacenamiento.ObtenerDirectorioHasheado("Controllers", profundo: true);
// Obtener el hash actual del contenido del directorio
var hashActual = hasher.HashActual;