Ejercicio resuelto. Gracias por la ayuda.

Iniciado por Droigor, 21 Marzo 2014, 20:58 PM

0 Miembros y 2 Visitantes están viendo este tema.

Droigor

Recientemente pedí ayuda en el lugar equivocado de este foro.

Gracias a la ayuda y los buenos consejos recibidos no solo he aprendido un montón si no que además me han puesto una buena nota :)

Inicialmente empecé trabajando con un fichero de texto plano, pero me pareció un sistema muy farragoso y opté por trabajar con objetos directamente.
Pego el enlace al post original y los códigos del programa por si a alguien le valen de algo.

Muchas gracias.

http://foro.elhacker.net/java/ayuda_con_un_ejercicio_grabar_datos_en_un_fichero_secuencial_de_texto-t410283.0.html

Clase Principal:
public class Tarea6_3 implements java.io.Serializable {
    //Se implementa la interfaz serializable para que el objeto Cliente pueda
    //escribir todos sus datos en fichero.

    /**
     * @param args the command line arguments
     * @throws java.lang.Exception
     */
    public static void main(String[] args) throws Exception {

        /**
         * Menú
         * Presenta el menú de operaciones con todas las opciones disponibles
         */
        int opcion = 0;
        do{
            try{
                opcion = Integer.parseInt(Menu()); // Mostramos el menu
                }
            catch (NumberFormatException nfe){
                System.out.println(nfe.getMessage());
                opcion = 10;
            }
        switch (opcion){
        case 0://Salir del menú
        break;
           
        case 1: //Añadir cliente
            //Creamos un nuevo objeto cliente de la clase Clientes
            Clientes cliente = new  Clientes(Clientes.setNombre(),
                                    Clientes.setNif(),
                                    Clientes.setTlf(),
                                    Clientes.setDireccion(),
                                    Clientes.setDeuda());
            //Llamada al método guardarEnArchivo.
            Archivo.guardarClienteEnArchivo("clientes.dat", cliente);
        break;
                       
        case 2: //Listar clientes
            Archivo.listarClientes();
        break;

        case 3: //Buscar clientes.
            Archivo.buscarCliente();
        break;
           
           
        case 4://Borrar cliente
            Archivo.borrarCliente();
        break;

        case 5://Borrar fichero de clientes. Ojo que no hay vuelta atrás.
            Archivo.borrarClientesDat();
        break;

        default:
        System.out.println("Introduzca un valor entre 0 y 6");
        }
    }while (opcion !=0);
  }

    /**
     * menu()
     * Menú de selección. Presenta el menú de opciones
     * @return opcion
     */
    public static String Menu() {
        System.out.println("Men\u00fa");
        System.out.println("-------------------------------");
        System.out.println("1 - A\u00f1adir cliente");
        System.out.println("2 - Listar clientes");
        System.out.println("3 - Buscar cliente");
        System.out.println("4 - Borrar cliente");
        System.out.println("5 - Borrar fichero clientes.dat");
        System.out.println("0 - Salir");
        System.out.println("-------------------------------");
        String opcion = Archivo.sc.next();
        return opcion;
    }
}



Clase Archivo.
package tarea6_3;

import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Recoge todos los métodos necesarios para manipular el archivo clientes.dat
* @author adec29
*/
public class Archivo implements java.io.Serializable {
    //Inicializo los miembros de clase.
    private static FileOutputStream fos;
    private static ObjectOutputStream salida;
    private static FileInputStream fis;
    private static ObjectInputStream entrada;
    final static String temporal = "temporal.dat";
    final static String archivo = "clientes.dat";
    static Scanner sc=new Scanner(System.in); //Para leer de teclado
    static boolean check;// para hacer comprobaciones
   
    /**
     * Comprueba si clientes.dat tiene registros
     * @return check
     */
    private static boolean tieneRegistros(){
        //Inicialmente presuponemos que no tenemos registros en clientes.dat
        check = false ;
        Clientes cliente = null ;

        try {
            //Abrimos el archivo para lectur.
            fis = new FileInputStream(archivo);
            entrada = new ObjectInputStream(fis);
            // Lee el primer objeto del fichero
            cliente = (Clientes) entrada.readObject();
            //Hacemos la comprobación.
            if (cliente != null){ //Si el objeto cliente tiene algo.
                check = true ;    //tieneRegistros() devuelve true
            }

        } catch (FileNotFoundException  e) {
            System.out.println( "Fichero no encontrado en tieneRegistros()"+e ) ;
        } catch (IOException | ClassNotFoundException ex) {
            System.out.println( "Capturada excepción en tieneRegistros()"+ex ) ;
        }

        return(check) ;
    }   
   
    /**
     * Lee los clientes de clientes.dat
     * @throws java.io.IOException
     */
    public static void listarClientes () throws IOException {
        //Preparamos un objeto de la clase Cliente para poder mostrar su
        //contenido cuando leamos.
        Clientes cliente = null;
       
        try {
            //Como vamos a listar solamente, no vamos a modificar nada, abrimos
            //clientes.dat en modo lectura.
            fis = new FileInputStream(archivo);
            entrada = new ObjectInputStream(fis);
            //Comprobamos que hay algo en el flujo de datos fis
            if (fis != null){
                do{
                //Leemos el primer objeto cliente a través del buffer "entrada"
                //que antes vinculamos al flujo de datos "fis" que lee el
                //archivo clientes.dat
                cliente = (Clientes) entrada.readObject();
                            System.out.println(
                             cliente.getNombre()+" "
                            +cliente.getNif()+" "
                            +cliente.getDireccion()+" "
                            +cliente.getTlf()+" "
                            +cliente.getDeuda());
                //Pero esto sólo lee el primer cliente, si queremos leerlos
                //todos habrá que repetir hasta llegar al último.                           
                }while (cliente != null);
            }   //Cerramos el archivo.
                fis.close();
                entrada.close();
        } catch (EOFException eof) {
            System.out.println("¡Fin del fichero!");
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(Archivo.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
   
   
    /**
     * Nos posibilita la escritura de un nuevo registro en clientes.dat
     * @param archivo
     * @param cliente
     */
    public static void guardarClienteEnArchivo(String archivo,
                                                Clientes cliente) {
        try {
            //Creamos un fujo de salida hacia clientes.dat
            fos = new FileOutputStream(archivo, true);
            if (tieneRegistros() == true){
                //Si clientes.dat YA tiene registros.
                //El fujo ObjectOutputStream es el que procesa los datos de
                //salida y se ha de vincular a un objeto de la clase
                //FileOutputStream.(Serializar)
                salida = new MiObjectOutputStream (fos);
                ////////////////////////////////////////////////////////////////
                // ¿Por qué usamos MiObjectOutputStream?                      //
                // Visita esta página. Muy bien explicado.
                // http://www.chuidiang.com/java/ficheros/ObjetosFichero.php  //
                ////////////////////////////////////////////////////////////////               
            }
            else {
                //Si no tiene registros uso la clase ObjectOutputStream para
                //escribir la cabecera y el PRIMER registro
                salida = new ObjectOutputStream (fos);
            }     
            //Grabar cliente
            if (fos != null) {salida.writeObject(cliente);}
            //Cerrar archivo.
            fos.close();
            salida.close();
          //Captura de excepciones.
        } catch (IOException ex) {
            System.out.println("Excepción capturada en guardarClienteEnArchivo"
                    +ex.getMessage());
        }
    }

    /**
     * Nos permite buscar un cliente a través de su dni
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static void buscarCliente() throws IOException,
                                              ClassNotFoundException {
        //Preparamos un objeto de la clase Cliente para poder mostrar su
        //contenido cuando leamos.
        Clientes cliente = null;
        //Preguntamos por el nif a buscar.
        String buscado = Clientes.setNif();
        try {
            //Como vamos a buscar solamente, no vamos a modificar nada, abrimos
            //clientes.dat en modo lectura.
            fis = new FileInputStream(archivo);
            entrada = new ObjectInputStream(fis);
            //Comprobamos que hay algo en el flujo de datos fis
            if (fis != null){
                do{
                //Leemos el primer objeto cliente a través del buffer "entrada"
                //que antes vinculamos al flujo de datos "fis" que lee el
                //archivo clientes.dat
                cliente = (Clientes) entrada.readObject();
                //Preguntamos por el cliente a buscar.
                String encontrado = cliente.getNif();
                //Comparamos buscado y encontrado
                if (buscado.equals(encontrado)){
                    System.out.println("Encontrado cliente."+
                            "\nNombre: "+cliente.getNombre()+
                            "\nNif: "+cliente.getNif()+
                            "\nDirección: "+cliente.getDireccion()+
                            "\nTlf: "+cliente.getTlf()+
                            "\nDeuda: "+cliente.getDeuda());
                }
                //Pero esto sólo lee el primer cliente, si queremos leerlos
                //todos habrá que repetir hasta llegar al último.
                }while (cliente != null);
                //Cerramos Archivo
                fis.close();
                entrada.close();
            }
        } catch (EOFException eof) {
            //No hagas nada
        } catch (ClassNotFoundException ex) {
            System.out.println(ex.getMessage());
        }
        //Informamos del fin de la búsqueda
        System.out.println("Búsqueda finalizada.");
    }

    /**
     * Borra un cliente que buscamos a través de su nif tantas veces como lo
     * encuentre dentro del fichero clientes.dat
     * Para ello creamos un fichero temporal.dat que guarda los clientes
     * que vamos leyendo excepto aquellos cuyo nif coincida con el buscaco.
     * Posteriormente renombramos clientes.dat a clientes.bak y renombramos
     * temporal.dat a clientes.dat.
     * Después borramos temporal.dat
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static void borrarCliente() throws IOException,
                ClassNotFoundException {
        //Preparamos un objeto de la clase Cliente para poder comparar su
        //contenido cuando leamos.
        Clientes cliente = null;
        //Preguntamos por el nif del cliente a borrar.
        String buscado = Clientes.setNif();
        try {
            //Vamos a buscar. Abrimos clientes.dat en modo LECTURA
            fis = new FileInputStream(archivo);
            entrada = new ObjectInputStream(fis);
            //Comprobamos que hay algo en el flujo de datos fis
            if (fis != null){
                do{
                //Leemos el primer objeto cliente a través del buffer "entrada"
                //que antes vinculamos al flujo de datos "fis" que lee el
                //archivo clientes.dat
                cliente = (Clientes) entrada.readObject();
                //Preguntamos por el nif del objeto cliente leido.
                String encontrado = cliente.getNif();
                //Comparamos buscado y encontrado
                if (buscado.equals(encontrado)){
                    System.out.println("Eliminado cliente."+
                            "\nNombre: "+cliente.getNombre()+
                            "\nNif: "+cliente.getNif()+
                            "\nDirección: "+cliente.getDireccion()+
                            "\nTlf: "+cliente.getTlf()+
                            "\nDeuda: "+cliente.getDeuda());
                }else {
                    Temporal.guardarClienteEnArchivoTemporal(temporal, cliente);
                }
                //Pero esto sólo lee el primer cliente, si queremos leerlos
                //todos habrá que repetir hasta llegar al último.
                }while (cliente != null);
                //Cerramos archivo.
                fis.close();
                entrada.close();;
            }
        } catch (EOFException eof) {
            //No hagas nada
        } catch (ClassNotFoundException ex) {
            System.out.println(ex.getMessage());
        }
        //Informamos del fin de la búsqueda
        System.out.println("Búsqueda finalizada.");
        //Renombramos, copiamos y borramos.
        //Creamos tres abstracciones usando la clase File
        File clientesDat = new File ("clientes.dat");
        File clientesBak = new File ("clientes.bak");
        File temp = new File ("temporal.dat");
        try {
            //Renombramos y comprobamos.
            check = clientesDat.renameTo(clientesBak);
            if (check) {
                System.out.println("clientes.dat renombrado a clientes.bak");
            } else {
                System.out.println("El renombrado no se ha podido realizar");
            }
            //Renombramos y comprobamos.
            check = temp.renameTo(clientesDat);
            if (check) {
                System.out.println("temporal.dat renombrado a clientes.dat");
            } else {
                System.out.println("El renombrado no se ha podido realizar");
            }
            //Borramos los clientes.bak que ya no lo necesitamos.
            check = clientesBak.delete();
            if (check) {
                System.out.println("clientes.bak borrado");
            } else {
                System.out.println("El borrado no se ha podido realizar");
            }
        } catch (Exception e) {
                        System.out.println(e.getMessage());

        }
    }
   
    /**
     * Borra el archivo clientes.dat
     */
    public static void borrarClientesDat(){
        //Instanciamos clientesDat la clase File y le pasamos el nombre del
        //fichero con el que vamos a trabajar
        File clientesDat = new File ("clientes.dat");
        //Para borrar el fichero deberemos de invocar el método .delete()
        //de la clase File. En caso de que se pueda realizar el borrado del
        //fichero, dicho método devolverá true.
        //En caso contrario devolverá false.
try {
            if (clientesDat.delete())//true
            {
                System.out.println("Fichero borrado con éxito");
            } else //false
            {
                System.out.println("No se ha podido borrar el fichero");
            }
        } catch (Exception e) {
                        System.out.println(e.getMessage());
        }
    }
}


Clase Cliente:
import java.util.Scanner;

/**
*
* @author adec29
*/
public class Clientes implements java.io.Serializable {
   
    //Inicializo los miembros de clase.
    static Scanner teclado=new Scanner(System.in); //Para leer de teclado
    static boolean check;// Para hacer comprobaciones
    //Inicializo atributos de clase
    private String nif; //Nif del cliente
    private String nombre; //Nombre del cliente
    private String telefono; // Teléfono del cliente
    private String direccion; // Dirección del cliente
    private String deuda; //Deuda del dliente

   
    /**
     * Constructor de la clase
     * Los datos son comprobados dentro del método que los crea
     * @param nombre
     * @param nif
     * @param telefono
     * @param direccion
     * @param deuda
     * @throws Exception
     */
       
    public Clientes(String nombre, String nif, String telefono,
                          String direccion, String deuda) throws Exception {
      Archivo.check = false;
      this.nombre = nombre;
      this.nif = nif;
      this.telefono = telefono;
      this.direccion = direccion;
      this.deuda = deuda;
  }
   
// Métodos set y get
   
     /**
     * setNombre()
     * @return nombre
     * Nos permite establecer el nombre del cliente. Verifica que el nombre
     * introducido es correcto siempre y cuando la longitud del String nombre
     * se halle entre 3 y 40 caracteres.
     */
    public static String setNombre(){
        String nombre = "x";
        do{
            System.out.println("Introduce el nombre del cliente (3-40 caracteres):");
            nombre = teclado.nextLine();
            if ((nombre.length() < 3) || (nombre.length() > 40))
                System.out.println("El nombre debe tener entre 3 y 40 caracteres");
            }
        while ((nombre.length() < 3) || (nombre.length() > 40));
        return nombre;
        }
   
     /**
     * setNif()
     * @return nif
     * Nos permite establecer el nif del cliente. Voy a dar por correcto una
     * cadena de 9 caracteres
     */
    public static String setNif(){
        String nif = "x";
        do{
            System.out.println("Introduce el nif del cliente (9 caracteres):");
            nif = teclado.nextLine();
            if ((nif.length() < 9) || (nif.length() > 9))
                System.out.println("El nif debe tener 9 caracteres");
            }
        while ((nif.length() < 9) || (nif.length() > 9));
        return nif;
        }
   
    /**
     * setTlf()
     * @return tlf
     * Nos permite establecer el teléfono del cliente. Voy a dar por correcto una
     * cadena de 9 caracteres
     */
    public static String setTlf(){
        String tlf = "x";
        do{
            System.out.println("Introduce el teléfono del cliente (9 caracteres):");
            tlf = teclado.nextLine();
            if ((tlf.length() < 9) || (tlf.length() > 9))
                System.out.println("El teléfono debe tener 9 caracteres");
            }
        while ((tlf.length() < 9) || (tlf.length() > 9));
        return tlf;
        }
   
     /**
     * setDireccion()
     * @return dir
     * Nos permite establecer la dirección del cliente. Asume que la dirección
     * introducida es correcta siempre y cuando la longitud del String dir
     * se halle entre 3 y 40 caracteres.
     */
    public static String setDireccion(){
        String dir = "x";
        do{
            System.out.println("Introduce la dirección cliente (10-50 caracteres):");
            dir = teclado.nextLine();
            if ((dir.length() < 3) || (dir.length() > 40))
                System.out.println("El nombre debe tener entre 10 y 50 caracteres");
            }
        while ((dir.length() < 10) || (dir.length() > 50));
        return dir;
        }
   
    /**
     * setDeuda
     * Nos permite establecer la cantidad que debe el cliente
     * @return deuda
     */
    public static String setDeuda() {
    String deuda;
    System.out.println("Indique la cantidad adeudada por el cliente: ");
    deuda = teclado.next();
    return deuda;
       
  }
   
    /**
     * getNif
     * Nos devuelve el nif del cliente
     * @return nif
     */
    public String getNif() {
        return nif;
    }

    /**
     * getNombre
     * Nos devuelve el nombre del cliente
     * @return nombre
     */
    public String getNombre() {
        return nombre;
    }

    /**
     * getTlf
     * Nos devuelve el teléfono del cliente
     * @return teléfono
     */
    public String getTlf() {
        return telefono;
    }

    /**
     * getDireccion
     * Nos devuelve la dirección del cliente
     * @return direccion
     */
    public String getDireccion() {
        return direccion;
    }

    /**
     * getDeuda
     * Nos devuelve la deuda que tiene el cliente
     * @return deuda
     */
    public String getDeuda() {
        return deuda;
    }
}


Clase temporal:

public class Temporal implements java.io.Serializable {
   
    private static FileInputStream fistemp;
    static final String temporal = "temporal.dat";
    private static ObjectInputStream entradatemp;
    private static ObjectOutputStream salidatemp;
    private static FileOutputStream fostemp;
    private static boolean tempcheck;

    /**
     * Nos posibilita la escritura de un nuevo registro en temporal.dat
     * @param temporal
     * @param cliente
     */
    public static void guardarClienteEnArchivoTemporal(String temporal,
                                                       Clientes cliente) {
        try {
            fostemp = new FileOutputStream(temporal, true);
            if (tieneRegistrosTemporal() == true) {
                salidatemp = new MiObjectOutputStream(fostemp);
            } else {
                salidatemp = new ObjectOutputStream(fostemp);
            }
              if (fostemp != null) {
                salidatemp.writeObject(cliente);
            }
            fostemp.close();
            salidatemp.close();
        } catch (IOException ex) {
            System.out.println("Excepci\u00f3n capturada en "
                    + "guardarClienteEnArchivo" + ex.getMessage());
        }
    }

     /**
     * Comprueba si temporal.dat tiene registros.
     */
    private static boolean tieneRegistrosTemporal() {
        tempcheck = false;
        Clientes cliente = null;
        try {
            fistemp = new FileInputStream(temporal);
            entradatemp = new ObjectInputStream(fistemp);
            cliente = (Clientes) entradatemp.readObject();
            if (cliente != null) {
                tempcheck = true;
            }
        } catch (FileNotFoundException e) {
            System.out.println("Fichero no encontrado en "
                    + "tieneRegistrosTemporal()" + e);
        } catch (IOException | ClassNotFoundException ex) {
            //no hagas nada
        }
        return tempcheck;
    }
}


Y por último, la solución a todos los problemas que tenía.
cito fuente:
http://www.chuidiang.com/java/ficheros/ObjetosFichero.php

y pego clase:

public class MiObjectOutputStream extends ObjectOutputStream
{
   
    public MiObjectOutputStream(OutputStream out) throws IOException
    {
        super(out);
    }

   
    protected MiObjectOutputStream() throws IOException, SecurityException
    {
        super();
    }

   
    @Override
    protected void writeStreamHeader() throws IOException
    {
    }

}
Se bueno, ten un buen día.

Mitsu

#1
Hola, veo que ya respondiste el tema donde te ayudé en Java. No era necesario que crees el tema, pudiste haber actualizado tu post original para que aquel que siga el tema vea la transición, por cierto el tema lo abandonaste (En mi última respuesta te dejé todo el código que querías) pero nunca respondiste xD. Te sugiero que marques el tema original como Solucionado. Salu2.

Droigor

Pues te respondo ahora :)

Siento no haberlo hecho antes, me he dejado las pestañas en este trabajo, que tengo los exámenes el lunes y soy un despiste con patas en todo lo demás.

Comentarte que lo hice y lo entregué en primera instancia trabajando con archivo de texto plano tal y como me explicabas en el post y volví a hacerlo trabajando con objetos directamente que al final me pareció más adecuado.

Sea como sea, tus orientaciones iniciales me llevaron por el buen camino, que andaba más perdido que un elefante en una cristalería.

Un saludo.
Se bueno, ten un buen día.

Mitsu

#3
LOL, sí, Java es un lenguaje OO, así que hay que aprovecharlo, si no, mejor C xD. Siempre que puedas utiliza POO. Un saludo y espero hayas salido bien en el examen xD. Por cierto en el código que te puse en el tema original, usé objetos para trabajar con los ficheros, lo que faltó era usar flujos en la lectura y escritura ;) Salu2.