A Java library for structured file-based object persistence. This project allows you to define a data schema and store, retrieve, and manage Java objects in a single file with session recovery capabilities.
Este proyecto proporciona un framework ligero en Java para la persistencia de objetos en un único archivo. Permite definir un esquema de datos y almacenar, recuperar y gestionar objetos Java de forma estructurada, con capacidades para recuperar la sesión entre ejecuciones.
El objetivo principal de JavaFileHandler es ser parte de un proyecto meramente educativo.
Está diseñado para ser:
- Ligero: Sin dependencias externas, solo se usa la librería estándar de Java.
- Estructurado: Permite definir un "encabezado" (schema) y añadir elementos que siguen esa estructura.
- Persistente: Los datos se guardan en un único archivo (
FileHelperStructure.dat). - Resiliente: Puede recuperar el estado y la estructura de una sesión anterior.
- ✅ Almacenamiento Estructurado: Define un esquema con encabezados y definiciones de campo.
- ✅ Serialización de Objetos: Almacena y recupera objetos Java de forma transparente.
- ✅ Recuperación de Sesión: Guarda y restaura el estado del gestor de archivos entre ejecuciones.
- ✅ Tipos de Datos Flexibles: Soporte para varios primitivos y objetos a través del
enum DataType. - 🚧 Operaciones de Inserción: (Experimental) Inserción de objetos en medio de la estructura del archivo.
- 🚧 Obtención del fichero como lista: (Experimental) En un futuro se busca poder retornar la colección de objetos contenida en el fichero como una lista.
- 🚧 Operaciones de impresión: (Experimental) Todavía sin implementar completamente los métodos que permitan leer un fichero como secuencia de objetos.
⚠️ En Desarrollo: Este es un proyecto educativo y en desarrollo. Algunas características son experimentales o no están completamente implementadas.
El "framework" utiliza una clase principal, FileHelper, para orquestar toda la operación.
- Definición del Esquema: Se define un
header(el esquema principal) usandosetHeader. - Adición de Datos: Se añaden objetos al archivo usando
addObject, que los serializa y los almacena. - Gestión del Estado: El
FileHelpermantiene un puntero global y un registro de los elementos. - Recuperación: Al cerrar la sesión con
close(), el propio objetoFileHelperse serializa al final de otr archivo archivo para mantener la integridad del fichero original y en la próxima ejecución,recoverPreviusSession()puede leerlo para restaurar el estado completo.
El archivo resultante (FileHelperStructure.dat) tiene esta estructura lógica:
[Header] + [Objeto 1] + [Objeto 2] + ... + [Objeto N] + [Objeto FileHelper Serializado]
Dado que Main.java está vacío, aquí tienes un ejemplo completo de cómo usarías el framework en tu propia aplicación(puede no funcionar dado que todavía está en desarrollo).
import Utilities.FileHelper;
import java.io.RandomAccessFile;
import java.io.IOException;
import java.lang.IllegalAccessException;
public class MiAplicacion {
public static void main(String[] args) {
// Usamos 'rw' para leer y escribir. El archivo se creará si no existe.
try (RandomAccessFile raf = new RandomAccessFile(FileHelper.fileName, "rw")) {
FileHelper fileHelper = new FileHelper();
// Si el archivo está vacío, es la primera vez que ejecutamos.
if (raf.length() == 0) {
System.out.println("Creando nueva estructura de archivo...");
// 1. Definir el encabezado (ej. un ID único para el conjunto de registros)
fileHelper.setHeader(raf, "ID-Conjunto-De-Datos-2024", "recordSetId");
// 2. Añadir algunos objetos de datos
fileHelper.addObject(raf, "Primer entrada de datos", "entry1");
fileHelper.addObject(raf, "Otra entrada más", "entry2");
fileHelper.addObject(raf, 98765, "numericEntry");
fileHelper.addObject(raf, 3.14159f, "floatEntry");
System.out.println("Datos añadidos. Elementos totales: " + fileHelper.getElements());
} else {
// Si el archivo ya existe, recuperamos la sesión anterior.
System.out.println("Recuperando sesión anterior...");
fileHelper.recoverPreviusSession();
System.out.println("Sesión recuperada. Elementos totales: " + fileHelper.getElements());
System.out.println("Estado del FileHelper: " + fileHelper.toString());
}
// 3. Siempre guardar el estado antes de salir
fileHelper.close();
System.out.println("Sesión guardada exitosamente.");
} catch (IOException | ClassNotFoundException | IllegalAccessException e) {
System.err.println("Ocurrió un error: " + e.getMessage());
e.printStackTrace();
}
}
}El núcleo del proyecto reside en el paquete Utilities.
Propósito: Es la clase principal y el punto de entrada para el usuario. Orquesta todas las operaciones de alto nivel.
Funciones Clave:
- Gestión del Estado: Mantiene el encabezado (
header), las definiciones de campo (fieldDefinitions), el puntero global (globalPointer) y el número de elementos (elements). setHeader(): Define el esquema principal del archivo. Solo se puede llamar una vez.addObject(): Añade un nuevo objeto al final del archivo, registrando suFieldDefinition.recoverPreviusSession(): Lee el objetoFileHelperserializado al final del archivo para restaurar el estado completo.close(): Serializa el estado actual delFileHelpery lo escribe al final del archivo para la próxima recuperación.
Propósito: Es el motor de bajo nivel que interactúa directamente con el RandomAccessFile. Maneja la lectura y escritura de bytes.
Funciones Clave:
- Serialización/Deserialización: Usa
Convert.javapara transformar objetos a bytes y viceversa. - Gestión de Tamaños: Ofrece métodos para manejar objetos cuyo tamaño se guarda con un
int(...AsInt) o unlong(...AsLong). - Operaciones CRUD:
getObjectAs...(): Lee un objeto desde una posición específica.setObjectAs...(): Escribe un objeto en una posición específica.addObjectLastAs...(): Añade un objeto al final del archivo.addObjectInAs...(): (Experimental) Inserta un objeto en una posición, desplazando el resto de los datos.
- Métodos de Utilidad: Incluye funciones para imprimir el contenido del archivo o convertirlo en listas (
LinkedList,ArrayList).
Propósito: Es una clase de datos que actúa como metadato para cada campo almacenado. Describe el nombre, el tipo y el tamaño de un objeto(todavía sin nua implementación real por el momento).
Funciones Clave:
- Constructor por Inferencia:
FieldDefinition(Object o, String name)deduce elDataTypea partir de una instancia de objeto. - Constructor por Tipo:
FieldDefinition(DataType dataType)(marcado como "Por implementar") permite crear una definición a partir del enumDataType. Nota: Este constructor está incompleto y es una área clave para el desarrollo futuro. - Getters: Proporciona acceso al nombre, tipo y tamaño del campo.
Propósito: Una clase de utilidad simple y estática para la serialización.
Funciones Clave:
toBytes(Object object): Convierte cualquier objeto serializable en un array de bytes.toObject(byte[] bytes): Convierte un array de bytes de vuelta a un objeto.
Propósito: Un enum que define todos los tipos de datos soportados por el framework.
Funciones Clave:
- Proporciona una lista tipada y segura de los tipos de datos que pueden ser manejados (primitivos, objetos, arrays, etc.). Esto es fundamental para la definición del esquema.
Propósito: Este script no es parte de la librería Java. Es una herramienta de desarrollo utilizada para generar el archivo context.txt que se adjuntó junto con él.
Función:
- Recorre el directorio del proyecto.
- Identifica los tipos de archivo por su extensión.
- Crea un único archivo de texto (
context.txt) que contiene el contenido de todos los archivos del proyecto, formateado para su fácil visualización. Es útil para compartir o analizar el codebase completo de una sola vez.
Este proyecto se considera Work in Progress (WIP).
- Completado: El flujo básico de crear, añadir datos y recuperar la sesión funciona.
- Por Implementar:
- El constructor
FieldDefinition(DataType dataType)necesita ser completado para asignarfieldSizecorrectamente para todos los tipos. - Los métodos de inserción (
addObjectInAs...) enObjectHandlerson experimentales y pueden necesitar más pruebas y depuración. - No hay implementación para leer o modificar objetos específicos (solo se pueden añadir al final, en una posición(haciendo corrimiento o reemplazando) o recuperar la sesión completa).
- El constructor
- Clona este repositorio.
- Asegúrate de tener un JDK (Java Development Kit) instalado (versión 17 o superior recomendada(debería funcionar en la versión 8)).
- Importa el proyecto en tu IDE favorito (IntelliJ, Eclipse, etc.)(O puedes importar simplemente el paquete
Utilitiesen tu propio proyecto). - El paquete
Utilitiesestá listo para ser utilizado en tus propias clases.