import java.io.*;

public class Ficheros
{
  private class CRegistro
  {
    String nombre;
    float nota;
  }

  // Flujos
  private PrintStream flujoS = System.out; // salida estándar
  private DataInputStream dis1 = null;// entrada de datos desde el fichero1
  private File fichero1 = null;       // objeto que identifica el fichero1
  private DataInputStream dis2 = null;// entrada de datos desde el fichero2
  private File fichero2 = null;       // objeto que identifica el fichero2
  private DataOutputStream dos = null;// salida de datos hacia el fichero final
  private File fichero = null;        // objeto que identifica el fichero final

  public void abrir(String nomFichero1, String nomFichero2)
    throws IOException
  {
    // Crear un objeto File que identifique al fichero1
    fichero1 = new File(nomFichero1);

    // Verificar si el fichero existe
    if (fichero1.exists())
    {
      // Si existe, abrir un flujo desde el mismo
      dis1 = new DataInputStream(new BufferedInputStream(
                                 new FileInputStream(fichero1)));        
    }
    else
    {
      flujoS.println("El fichero " + nomFichero1 + " no existe");
      return;
    }

    // Crear un objeto File que identifique al fichero2
    fichero2 = new File(nomFichero2);

    // Verificar si el fichero existe
    if (fichero2.exists())
    {
      // Si existe, abrir un flujo desde el mismo
      dis2 = new DataInputStream(new BufferedInputStream(
                                 new FileInputStream(fichero2)));        
    }
    else
    {
      flujoS.println("El fichero " + nomFichero2 + " no existe");
      return;
    }
        
    // Crear un objeto File que identifique al fichero final
    fichero = new File("temporal");

    // Abrir un flujo hacia el mismo
    dos = new DataOutputStream(new BufferedOutputStream(
                               new FileOutputStream(fichero)));        
  }

  public void fusionar() throws IOException
  {
    // Variables para leer desde el fichero1
    CRegistro regF1 = new CRegistro();
    boolean finFichero1 = false;

    // Variables para leer desde el fichero2
    CRegistro regF2 = new CRegistro();
    boolean finFichero2 = false;

    int i; // resultado de una comparación

    try
    {
      // Leer un un nombre y una nota desde
      // el fichero1. Cuando se alcance el final del fichero Java
      // lanzará una excepción del tipo EOFException.
      regF1.nombre = dis1.readUTF();
      regF1.nota = dis1.readFloat();

      // Leer un un nombre y una nota desde
      // el fichero2. Cuando se alcance el final del fichero Java
      // lanzará una excepción del tipo EOFException.
      regF2.nombre = dis2.readUTF();
      regF2.nota = dis2.readFloat();

      while (true)
      {
        if (finFichero1 && finFichero2) break;

        i = regF1.nombre.compareTo(regF2.nombre);

        // Forzar la comparación a un valor determinado si alguno
        // de los dos ficheros finalizó, para que lea y grabe del
        // que aún no finalizó.
        if (finFichero1)
          i = 1;
        else if (finFichero2)
          i = -1;

        if (i == 0) // regF1.nombre == regF2.nombre
        {
          // El mismo alumno. Grabar regF2
          dos.writeUTF(regF2.nombre);
          dos.writeFloat(regF2.nota);

          // Leer de nuevo de ambos ficheros
          try
          {
            regF1.nombre = dis1.readUTF();
            regF1.nota = dis1.readFloat();
          }
          catch(EOFException e)
          {
            flujoS.println("Fin del fichero1");
            finFichero1 = true;
          }

          try
          {
            regF2.nombre = dis2.readUTF();
            regF2.nota = dis2.readFloat();
          }
          catch(EOFException e)
          {
            flujoS.println("Fin del fichero2");
            finFichero2 = true;
          }
          continue;
        }                                                     
        else if (i > 0) // regF1.nombre > regF2.nombre
        {
          // Grabar regF2
          dos.writeUTF(regF2.nombre);
          dos.writeFloat(regF2.nota);

          // Leer de nuevo de fichero2
          try
          {
            regF2.nombre = dis2.readUTF();
            regF2.nota = dis2.readFloat();
          }
          catch(EOFException e)
          {
            flujoS.println("Fin del fichero2");
            finFichero2 = true;
          }
          continue;
        }
        else // regF2.nombre > regF1.nombre
        {
          // Grabar regF1
          dos.writeUTF(regF1.nombre);
          dos.writeFloat(regF1.nota);

          // Leer de nuevo de fichero1
          try
          {
            regF1.nombre = dis1.readUTF();
            regF1.nota = dis1.readFloat();
          }
          catch(EOFException e)
          {
            flujoS.println("Fin del fichero1");
            finFichero1 = true;
          }
        }
      }

    }
    catch(EOFException e)
    {
      flujoS.println("Fin del fichero1 y fichero2");
    }
    finally
    {
      // Cerrar flujos
      if (dis1 != null) dis1.close();
      if (dis2 != null) dis2.close();
      if (dos != null) dos.close();
      // Copiar en el fichero alumnos todos los registros del temporal
      // excepto los que en el campo nota tengan -1.
      copiar("alumnos", "temporal");
    }
  }

  public void copiar(String nomFichero1, String nomFichero2)
    throws IOException
  {
    // Copiar nomFichero2 en nomFichero1

    // Crear un objeto File que identifique al fichero2
    fichero2 = new File(nomFichero2);

    // Verificar si el fichero existe
    if (fichero2.exists())
    {
      // Si existe, abrir un flujo desde el mismo
      dis2 = new DataInputStream(new BufferedInputStream(
                                 new FileInputStream(fichero2)));        
    }
    else
    {
      flujoS.println("El fichero " + nomFichero2 + " no existe");
      return;
    }
        
    // Crear un objeto File que identifique al fichero1
    fichero = new File(nomFichero1);

    // Abrir un flujo hacia el mismo
    dos = new DataOutputStream(new BufferedOutputStream(
                               new FileOutputStream(fichero)));

    // Variable para leer desde el fichero2
    CRegistro regF2 = new CRegistro();

    try
    {
      while (true)
      {
        // Leer del fichero2
        regF2.nombre = dis2.readUTF();
        regF2.nota = dis2.readFloat();

        // Escribir en el fichero1
        if (regF2.nota != -1)
        {
          dos.writeUTF(regF2.nombre);
          dos.writeFloat(regF2.nota);
        }
      }
    }
    catch(EOFException e)
    {
      flujoS.println("Fin de la copia");
    }
    finally
    {
      // Cerrar flujos
      if (dis2 != null) dis2.close();
      if (dos != null) dos.close();
      // Borrar el fichero temporal
      fichero2.delete();
    }
  }
}
