//Autor: rafael Angel Montero Fernández.
//Fecha: Domingo 15 de Julio del 2018.
//
//El siguente codigo permite crear aplicasiones al estilo de bases de datos personalizadas.
//Ya no tendras que preocuparte si actualizan al servidor y tu base de datos debe migrar.
//¿Por qué mejor no crear la de uno mismo personalmente?
//No lleva interfaz grafica porque no se necesita. Solo se esta publicando lo que usted pueda integrar a su proyecto.
//Sin embargo mejor si le hago una interfaz grafica.
//pero para ello el registro debe ser más simplificado.
//Necesarios para escribir archivos
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import javax.swing.JOptionPane;
//Necesario para leer archivos
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.JOptionPane;
//Necesario para crear el registro.
import java.util.ArrayList;
import javax.swing.table.DefaultTableModel;
/**
Y ahora los objetos class y sus objetos internos.
*/
abstract class Continium extends Leer_archivo
{
/**
*Permite guardar las lineas de registros.
*/
protected String mRegistros[]={};
/**
* Permite guardar los datos ceparados de acuerdo a sus propiedades.
*/
protected String mPropiedades[]={};
private Escribir_archivo escribir=null;
public Continium(String nuevo_nombre_de_archivo)
{
escribir=new Escribir_archivo(nuevo_nombre_de_archivo);
this.setNombre_de_archivo(nuevo_nombre_de_archivo);
leer_archivo();
}
/**
* Sirve para proporcionar a algun modelo los datos o el objeto almacenado en alguna lista.
* @param id Indice del registro, cuando se escribe.
*/
protected abstract void escribiendo_un_registro(int id);
/**
*
* @param id Indice de la propiedad, depende de como las haya enumerado usted.
* @return Retorna los datos de esa propiedad pero dentro de escribir...
*/
public abstract String getDatos_de_la_propiedad(int id);
/**
* Escribe informacion en un archivo.
* @param nueva_cantidad_de_registros Una cantidad para identificar cuantos registros hay en su objeto.
* Recuerde proporcionarlo con length-1 o con size()-1.
* @param nueva_cantidad_de_propiedades Cuantas propiedades tiene su objeto modelo.
* Recuerde contar desde cero o sea si su objeto tiene 4 propiedades entonces proporcione el numero 3.
*/
public void escribir(int nueva_cantidad_de_registros, int nueva_cantidad_de_propiedades)
{
String datos="";
for(int i=0; i<=nueva_cantidad_de_registros; i++)
{
this.escribiendo_un_registro(i);
int id=0;
while(id<=nueva_cantidad_de_propiedades)
{
datos+= getDatos_de_la_propiedad(id) + this.CEPARADOR_DE_PROPIEDADES;
id++;
}
datos+=this.CEPARADOR_DE_REGISTROS;
}
escribir.escribir_archivo(datos);
}
/**
* Por si quiere hacer que el archivo actue como una base de datos.
* Use esta constante para ceparar los registros.
*/
public final String CEPARADOR_DE_REGISTROS=" endRegistro ";
/**
* Por si quiere hacer que el archivo actue como una base de datos.
* Use esta constante para ceparar las propiedades o etiquetas de los datos.
*/
public final String CEPARADOR_DE_PROPIEDADES=" endpropiedad ";
@Override
public void recorriendo_datos(String datos) {
}
/**
*
* @param propiedad Datos de la propiedad correspondiente al indice.
* @param id Numero de indice de la propiedad.
*/
public abstract void recorriendo_propiedades(String propiedad, int id);
/**
* Se repita hasta que se recorran todos los registros.
* @param max Se carga con el macimo de las propiedades, en el procedimiento recorrido_finalizado.
*/
public abstract void cantidad_de_propiedades(int max);
/**
*
* @param max Se carga con el macimo de los registros, en el procedimiento recorrido_finalizado.
*/
public abstract void cantidad_de_registros(int max);
@Override
public void recorrido_finalizado(String todo_el_bloque_de_datos) {
mRegistros=todo_el_bloque_de_datos.split(this.CEPARADOR_DE_REGISTROS);
this.cantidad_de_registros(mRegistros.length);
for(int i=0; i<=mRegistros.length-1; i++)
{
mPropiedades=mRegistros[i].split(this.CEPARADOR_DE_PROPIEDADES);
this.cantidad_de_propiedades(mPropiedades.length);
int id=0;
while(id<=mPropiedades.length-1)
{
try{
this.recorriendo_propiedades(mPropiedades[id], id);
}catch(Exception ex){}
id++;
}
}
this.recorrido_terminado();
}
/**
* Sucede al final de recorrido_finalizado.
*/
public abstract void recorrido_terminado();
}
/////////////////////////////////////////////////////
abstract class Leer_archivo
{
/**
* Le da la extencion al archivo, a mi preferencia .txt
*/
private final String EXTENCION_DE_ARCHIVO=".txt";
private File flArchivo;
private String Ruta_del_archivo="";
//private FileDialog fdAbrir;
private FileReader frArchivo =null;
private BufferedReader bwLector=null;
private String mDatos[];
private String nombre_de_archivo=""; //Esta variable puede ser pasada al encavezado del class o quedarse aqui.
/**
* Evento del class, sucede cuando se recorren los datos en leer_archivo().
* Cada llamada recupera una linea de datos. En este caso sería un bloque entero de datos por linea.
* @param datos Bloque entero de datos.
*/
public abstract void recorriendo_datos(String datos);
/**
* Sucede al finalizar el recorrido de los datos en leer_archivo().
* Uselo es más efectivo.
* @param todo_el_bloque_de_datos Se pasa por parametro todos los datos compilados en la lectura.
*/
public abstract void recorrido_finalizado(String todo_el_bloque_de_datos);
public Leer_archivo()
{
//fdAbrir=new FileDialog(fdAbrir, "Abrir archivo", FileDialog.LOAD);
// Ruta_del_archivo="";
try{ frArchivo =new FileReader("Archivo"+ this.EXTENCION_DE_ARCHIVO);}catch(IOException ex){/*mensaje de error por si se quiere verificar que sucede*/}
setNombre_de_archivo("Archivo");
}//constructor.
public Leer_archivo(String nombre_de_archivo)
{
this.setNombre_de_archivo(nombre_de_archivo+ this.EXTENCION_DE_ARCHIVO);
try{ frArchivo =new FileReader(this.getNombre_de_archivo());}catch(FileNotFoundException ex){/*mensaje de error por si se quiere verificar que sucede*/}
}//constructor.
public String leer_archivo()
{
String respuesta="";
flArchivo=new File(this.getNombre_de_archivo() + this.EXTENCION_DE_ARCHIVO);
if(flArchivo.exists()==true)
{
//Este bloque de codigo obligatoriamente debe ir dentro de un try.
try{
frArchivo=new FileReader(flArchivo);
bwLector=new BufferedReader (frArchivo);
}catch(Exception e){}
String linea_de_texto="";
try{
while ((linea_de_texto=bwLector.readLine())!=null)
{
this.recorriendo_datos(linea_de_texto);
respuesta+=linea_de_texto+"\n";//Se le pone "\n" al final porque el codigo lo abre pero omitiendo los saltos de liena, entonces, deben volverse a escribir los saltos de linea.
}
}catch(Exception ex){}
this.recorrido_finalizado(respuesta);
try{
bwLector.close();//Se cierra el archivo.
}catch(Exception c){}
//Este condicional no afecta en nada la forma de guardar el archivo pero si es bueno usarlo para no borrar un trabajo previo.
//respuesta+="El archivo ya existia y ha sido sobreescrito posiblemente con informacion diferente. \nEn la direccion: " + flArchivo.getPath( ) ;
}//if
else
{
JOptionPane.showMessageDialog(null, "El archivo "+ this.getNombre_de_archivo() + this.EXTENCION_DE_ARCHIVO + " no existe.");
}
return respuesta;
}
public String []getList_de_datos()
{
return mDatos;
}//get
public ArrayList<String> getRegistros()
{
//De esta manera se evita escribir codigo extra en el class formulario.
//Se crea un ArrayList local
ArrayList<String> rsRespuesta=new ArrayList<String>();
//Se recorre mDatos.
//i<=mDatos.length-2 para no agregar el ultimo elemento que esta en blanco.
for (int i=0; i<=mDatos.length-2; i++)
{
rsRespuesta.add(mDatos[i]);//Se carga el ArrayList local con los datos del vector mDatos.
}//for
return rsRespuesta;
}//get
public void setNombre_de_archivo(String nuevo_nombre_de_archivo)
{
/* //Propiedad para guardar la direccion del archivo.*/
nombre_de_archivo= nuevo_nombre_de_archivo;//Debe escribir un valor aqui.
}//setDireccion
public String getNombre_de_archivo()
{
/*//Propiedad para guardar la direccion del archivo.*/
return nombre_de_archivo;
}//getDireccion
}
////////////////////////////////////////////
class Escribir_archivo
{
/**
* Le da la extencion al archivo, a mi preferencia .txt
*/
private final String EXTENCION_DE_ARCHIVO=".txt";
private File file_Archivo;
private String nombre_de_archivo="";
private BufferedWriter bwEscritor;
private FileWriter fwArchivo_en_el_que_escribir;
//private FileDialog fdGuardar;
private String vDireccion=""; //Esta variable puede ser pasada al encavezado del class o quedarse aqui.
public Escribir_archivo()
{
//fdGuardar=new FileDialog(fdGuardar, "Guardar como", FileDialog.SAVE);
nombre_de_archivo="";
file_Archivo=new File("Archivo"+EXTENCION_DE_ARCHIVO);
}//Constructor
public Escribir_archivo(String nuevo_nombre_de_archivo)
{
nombre_de_archivo=nuevo_nombre_de_archivo;
file_Archivo=new File(nombre_de_archivo+EXTENCION_DE_ARCHIVO);
this.setNombre_de_archivo(nombre_de_archivo);
}//Constructor
/**
* Escribe datos en un archivo de texto.
* @param texto_a_guardar Datos que se guardarán en el archivo.
* @return Retorna informacion relacionada con las acciones tomadas para guardar el archivo.
*/
public String escribir_archivo(String texto_a_guardar)
{
String mTextos[]=texto_a_guardar.split("\n");//Se detecta end_rs, se va colocando en el vector.
file_Archivo=new File(nombre_de_archivo + this.EXTENCION_DE_ARCHIVO);
try{
//Este bloque de codigo obligatoriamente debe ir dentro de un try.
fwArchivo_en_el_que_escribir=new FileWriter(file_Archivo);//De momento se deja hasta aqui, listo para escribir, se escribe en el momento de dar la orden.
for (int i=0; i<=mTextos.length-1;i++)
{
//Se va escribiendo cada linea en el archivo de texto.
fwArchivo_en_el_que_escribir.write(mTextos[i] + "\r\n" );//"\r\n" significa enter y retorno de carro.
}//for
//Este metodo escribe el archivo en el disco duro.
bwEscritor=new BufferedWriter(fwArchivo_en_el_que_escribir);
bwEscritor.close();//Se cierra el archivo.
}catch(Exception ex){JOptionPane.showMessageDialog(null,ex.getMessage());}
String respuesta="";
//Este condicional no afecta en nada la forma de guardar el archivo pero si es bueno usarlo para no borrar un trabajo previo.
if(file_Archivo.exists())
{
respuesta="El archivo ya existia y ha sido sobreescrito posiblemente con informacion diferente. \nEn la direccion: " + file_Archivo.getPath( ) ;
}//if
else
{
respuesta="El archivo ha sido creado exitosamente.\nEn la direccion: " + file_Archivo.getPath( ) ;
}//else*/
return respuesta;
}//escribir_archivo
/**
* Propiedad para guardar la direccion del archivo.
* @param nuevo_nombre_de_archivo Un texto que represente una url o el nombre del archivo.
*/
public void setNombre_de_archivo(String nuevo_nombre_de_archivo)
{
vDireccion= nuevo_nombre_de_archivo;//Debe escribir un valor aqui.
}//setDireccion
/**
* Propiedad para guardar la direccion del archivo.
* @return Retorna la direccion donde se guardan los archivos.
*/
public String getNombre_de_archivo()
{
return vDireccion;
}//getDireccion
}
/////////////////////////////////////////////////////
interface Rs<R>
{
/**
*
* @param nuevo Nuevo objeto a ser agregado.
*/
public void agregar(R nuevo);
/**
*
* @param nuevo El codigo del producto pasado por parametro.
* @return Busca la informacion, la encuentra y retorna true. No la encuentra retorna false.
*/
public R buscar(String nuevo);
/**
* Elimina el registrado de acuerdo a la ultima busqueda realizada.
* @param nuevo
*/
public void eliminar(String nuevo);
/**
*
* @return Retorna un objeto DefaultTableModel cargado de datos para mostrarlos en una tabla.
*/
public DefaultTableModel getReporte();
/**
*
* @param nuevo Un objeto con los datos actualizados para modificar un registro existente.
*/
public void modificar(R nuevo);
/**
*
* @return El total de registros del objeto.
*/
public int getTotal_de_registros();
/**
* Se puede usar en un for.
* Recorre el ArrayList... devolviendo un objeto a la vez.
* @param id Un numero que represente el indice de algun registro.
* @return Retorna un objeto con datos.
*/
public R get(int id);
}
///////////////////////////////////////////////////
//En esta parte va un pequeño ejemplo acerca de como implementarlo.
//Bueno ni tan pequeño porque es un poco grande pero servirá para visualizar todas las funcionalidades del codigo.
class Examen
{
public final String EXAMEN="Examen";
public final String PROFESOR="Profesor";
public final String AULA="Aula";
public final String PABELLON="Pabellon";
public final String DIA="Dia";
public final String HORA="Hora";
public Examen()
{
this.setExamen("");
this.setFecha("");
this.setHora("");
this.setPabellon("");
this.setAula("");
this.setProfesor("");
}
public Examen(String nuevo_Nombre_del_examen, String nuevo_Dia, String nuevo_Hora, String nuevo_Pabellon, String nuevo_Numero_de_aula, String nuevo_Nombre_del_profesor)
{
this.setExamen(nuevo_Nombre_del_examen);
this.setFecha(nuevo_Dia);
this.setHora(nuevo_Hora);
this.setPabellon(nuevo_Pabellon);
this.setAula(nuevo_Numero_de_aula);
this.setProfesor(nuevo_Nombre_del_profesor);
}
private String vNombre_del_examen=""; //Esta variable puede ser pasada al encavezado del class o quedarse aqui.
/**
*
*/
public void setExamen(String nuevo_Nombre_del_examen)
{
vNombre_del_examen= nuevo_Nombre_del_examen;//Debe escribir un valor aqui.
}//setNombre_del_examen
/**
*
* @return
*/
public String getExamen()
{
return vNombre_del_examen;
}//getNombre_del_examen
private String vNombre_del_profesor=""; //Esta variable puede ser pasada al encavezado del class o quedarse aqui.
/**
*
* @param nuevo_Nombre_del_profesor
*/
public void setProfesor(String nuevo_Nombre_del_profesor)
{
vNombre_del_profesor= nuevo_Nombre_del_profesor;//Debe escribir un valor aqui.
}//setNombre_del_profesor
/**
*
* @return
*/
public String getProfesor()
{
return vNombre_del_profesor;
}//getNombre_del_profesor
private String vNumero_de_aula=""; //Esta variable puede ser pasada al encavezado del class o quedarse aqui.
/**
*
* @param nuevo_Numero_de_aula
*/
public void setAula(String nuevo_Numero_de_aula)
{
vNumero_de_aula= nuevo_Numero_de_aula;//Debe escribir un valor aqui.
}//setNumero_de_aula
/**
*
* @return
*/
public String getAula()
{
return vNumero_de_aula;
}//getNumero_de_aula
private String vPabellon=""; //Esta variable puede ser pasada al encavezado del class o quedarse aqui.
/**
*
* @param nuevo_Pabellon
*/
public void setPabellon(String nuevo_Pabellon)
{
vPabellon= nuevo_Pabellon;//Debe escribir un valor aqui.
}//setPabellon
/**
*
* @return
*/
public String getPabellon()
{
return vPabellon;
}//getPabellon
private String fecha=""; //Esta variable puede ser pasada al encavezado del class o quedarse aqui.
/**
*
* @param nuevo_Dia
*/
public void setFecha(String nueva_fecha)
{
fecha= nueva_fecha;//Debe escribir un valor aqui.
}//setDia
/**
*
* @return
*/
public String getFecha()
{
return fecha;
}//getDia
private String vHora=""; //Esta variable puede ser pasada al encavezado del class o quedarse aqui.
/**
*
* @param nuevo_Hora
*/
public void setHora(String nuevo_Hora)
{
vHora= nuevo_Hora;//Debe escribir un valor aqui.
}//setHora
/**
*
* @return
*/
public String getHora()
{
return vHora;
}//getHora
}
//El registro.
class Examenes extends Continium implements Rs<Examen>
{
/**
*
*/
public Examenes()
{
super("Examenes");
this.leer_archivo();
}
private Examen un_examen=new Examen();
@SuppressWarnings("unchecked")
private ArrayList<Examen> rsExamenes=new ArrayList();
@Override
public void recorriendo_propiedades(String propiedad, int id) {
// System.out.println("\nId de la propiedad " + id + "\nDatos=" + propiedad);
switch(id)
{
case 0:
un_examen.setExamen(propiedad);
break;
case 1:
un_examen.setFecha(propiedad);
break;
case 2:
un_examen.setHora(propiedad);
break;
case 3:
un_examen.setPabellon(propiedad);
break;
case 4:
un_examen.setAula(propiedad);
break;
case 5:
un_examen.setProfesor(propiedad);
this.rsExamenes.add(un_examen);
un_examen=new Examen();
break;
}
}
@Override
public void cantidad_de_propiedades(int max) {
// System.out.println("Cantidad de propiedades " + max);
}
@Override
public void cantidad_de_registros(int max) {
// System.out.println("Cantidad de registros " + max);
}
@Override
public void recorrido_terminado() {
// System.out.println("Finalizó el recorrido de datos\n/////////////////////////////");
}
@Override
public void agregar(Examen nuevo) {
if(buscar(nuevo.getExamen()).getExamen().equals("")==true)
{
rsExamenes.add(nuevo);
}
else
{
// System.out.println("No se pudo agregar.");
}
}
@Override
public Examen buscar(String nuevo) {
for(int i=0; i<=rsExamenes.size()-1; i++)
{
if (rsExamenes.get(i).getExamen().equalsIgnoreCase(nuevo)==true)
{
return rsExamenes.get(i);
}
}
return new Examen();
}
@Override
public void eliminar(String nuevo) {
for(int i=0; i<=rsExamenes.size()-1; i++)
{
if (rsExamenes.get(i).getExamen().equalsIgnoreCase(nuevo)==true)
{
rsExamenes.remove(i);
}
}
}
@Override
public DefaultTableModel getReporte() {
DefaultTableModel dtmModelo=new DefaultTableModel();
String etiquetas_de_columnas[]={this.un_examen.EXAMEN, un_examen.DIA, un_examen.HORA, un_examen.PABELLON, un_examen.AULA, un_examen.PROFESOR};
String mExamen[]=new String[this.rsExamenes.size()], mDia[]=new String[this.rsExamenes.size()], mHora[]=new String[this.rsExamenes.size()], mPabellon[]=new String[this.rsExamenes.size()], mAula[]=new String[this.rsExamenes.size()], mProfesor[]=new String[this.rsExamenes.size()];
for (int i=0; i<=this.rsExamenes.size()-1; i++)
{
mExamen[i]=rsExamenes.get(i).getExamen();
mDia[i]=rsExamenes.get(i).getFecha();
mHora[i]=rsExamenes.get(i).getHora();
mPabellon[i]=rsExamenes.get(i).getPabellon()+"";
mAula[i]=rsExamenes.get(i).getAula();
mProfesor[i]=rsExamenes.get(i).getProfesor();
}
dtmModelo.addColumn(etiquetas_de_columnas[0], mExamen);
dtmModelo.addColumn(etiquetas_de_columnas[1], mDia);
dtmModelo.addColumn(etiquetas_de_columnas[2], mHora);
dtmModelo.addColumn(etiquetas_de_columnas[3], mPabellon);
dtmModelo.addColumn(etiquetas_de_columnas[4], mAula);
dtmModelo.addColumn(etiquetas_de_columnas[5], mProfesor);
return dtmModelo;
}
@Override
public void modificar(Examen nuevo) {
this.eliminar(nuevo.getExamen());
this.agregar(nuevo);
}
@Override
public int getTotal_de_registros() {
return this.rsExamenes.size();
}
@Override
public Examen get(int id) {
return rsExamenes.get(id);
}
/**
* @return Retorna los datos en un formato plano capaz de ser leídos en un reporte no cuadriculado.
* Pero si al estilo de una hoja de texto.
*/
@Override
public String toString()
{
String bloque_de_datos="";
for(int i=0; i<=this.rsExamenes.size()-1; i++)
{
// bloque_de_datos+= rsExamenes.get(i).getExamen() + this.CEPARADOR_DE_PROPIEDADES + rsExamenes.get(i).getFecha() + this.CEPARADOR_DE_PROPIEDADES + rsExamenes.get(i).getHora() + this.CEPARADOR_DE_PROPIEDADES + rsExamenes.get(i).getPabellon() + this.CEPARADOR_DE_PROPIEDADES + rsExamenes.get(i).getAula() + this.CEPARADOR_DE_PROPIEDADES + rsExamenes.get(i).getProfesor() + this.CEPARADOR_DE_PROPIEDADES + this.CEPARADOR_DE_REGISTROS;
bloque_de_datos+="Examen: " + rsExamenes.get(i).getExamen() + "\nDia: " + rsExamenes.get(i).getFecha() + "\nHora: " + rsExamenes.get(i).getHora() + "\nPabellon: " + rsExamenes.get(i).getPabellon() + "\nAula: " + rsExamenes.get(i).getAula() + "\nprofesor: " + rsExamenes.get(i).getProfesor() + "\n\n\n";
}
return bloque_de_datos;
}
public void guardar_en_disco()
{
this.setNombre_de_archivo("Examenes");
this.escribir(this.rsExamenes.size()-1, 5);
}
@Override
public String getDatos_de_la_propiedad(int id) {
switch(id)
{
case 0:
return un_examen.getExamen();
case 1:
return un_examen.getFecha();
case 2:
return un_examen.getHora();
case 3:
return un_examen.getPabellon();
case 4:
return un_examen.getAula();
case 5:
return un_examen.getProfesor();
}
return "";
}
@Override
protected void escribiendo_un_registro(int id) {
un_examen=this.rsExamenes.get(id);
}
}
//Un pequeño main para demostrar que funciona.
/**
Comentar que a lo largo de los años he ido conociendo acerca del funcionamiento de las bases de datos.
Los motores de servidores de bases de datos, lo cual me ha dado ideas y conocimientos suficientes como para crear mi propio servidor de bases de datos.
Se que el lector y muchas personas pueden crear codigos mucho más superiores y por una razon u otra no pueden hacerlos publicos.
Una muy dura es la razon del egoismo, pero el egoismo regresa porque no podrá ser visto por otros que lo puedan mejorar y republicar.
Ademas, otra razon es, ordenes de la empresa o coorporacion que proiben que sus empleados publiquen cualquier codigo, incluso de hechos por ellos mismos.
En mi caso no pertenesco a ninguna empresa ni me interesa pertenecer, asi que con gusto publico mis investigaciones, porque eso regresa.
Quizas alguien con mucho más habilidades podrá basarse en esto para crear algo realmente marabilloso.
El archivo se escribirá en la raíz del proyecto.
*/
public class Principal
{
private Examen un_examen=new Examen();
private Examenes rsExamenes=new Examenes();
public static void main(String args [])
{
un_examen=new Examen("Matematicas", "lunes 16 de julio del 2018", "9:00am", "2", "4A", "Yerico");
rsExamenes.agregar(un_examen);
un_examen=new Examen("Estadistica", "lunes 16 de julio del 2018", "1:00pm", "4", "1A", "Karina");
rsExamenes.agregar(un_examen);
System.out.println("Reporte\n" + rsExamenes.toString());
rsExamenes.guardar_en_disco();
rsExamenes.leer_archivo();
System.out.println("Reporte despues de la lectura del archivo\n" + rsExamenes.toString());
}
}