Leer y escribir datos primitivos

prev.gif (997 bytes)chapter.gif (1105 bytes)home.gif (1054 bytes)next.gif (998 bytes)

Entrada/salida

Los flujos de datos DataInputStream y DataOutputStream

Ejemplo: un pedido

El final del archivo


Los flujos de datos DataInputStream y DataOutputStream

La clase DataInputStream es útil para leer datos del tipo primitivo de una forma portable. Esta clase tiene un sólo constructor que toma un objeto de la clase InputStream o sus derivadas como parámetro.

Se crea un objeto de la clase DataInputStream vinculándolo a un un objeto FileInputStream para leer desde un archivo en disco denominado pedido.txt..

FileInputStream fileIn=new FileInputStream("pedido.txt");
DataInputStream entrada=new DataInputStream(fileIn));

o en una sola línea

DataInputStream entrada=new DataInputStream(new FileInputStream("pedido.txt"));

La clase DataInputStream define diversos métodos readXXX que son variaciones del método read de la clase base para leer datos de tipo primitivo

boolean readBoolean();
byte readByte();
int readUnsignedByte();
short readShort();
int readUnsignedShort();
char readChar();
int readInt();
String readLine();
long readLong();
float readFloat();
double readDouble();

La clase DataOutputStream es útil para escribir datos del tipo primitivo de una forma portable. Esta clase tiene un sólo constructor que toma un objeto de la clase OutputStream o sus derivadas como parámetro.

Se crea un objeto de la clase DataOutputStream vinculándolo a un un objeto FileOutputStream para escribir en un archivo en disco denominado pedido.txt..

FileOutputStream fileOut=new FileOutputStream("pedido.txt");
DataOutputStream salida=new DataOutputStream(fileOut));

o en una sola línea

DataOutputStream salida=new DataOutputStream(new FileOutputStream("pedido.txt"));

La clase DataOutputStream define diversos métodos writeXXX que son variaciones del método write de la clase base para escribir datos de tipo primitivo

void writeBoolean(boolean v);
void writeByte(int v);
void writeBytes(String s);
void writeShort(int v);
void writeChars(String s);
void writeChar(int v);
void writeInt(int v);
void writeLong(long v);
void writeFloat(float v);
void writeDouble(double v);

 

Ejemplo: un pedido

disco.gif (1035 bytes)archivo7: ArchivoApp7.java

En este ejemplo, se escriben datos a un archivo y se leen del mismo, que corresponden a un pedido

Observamos en la tabla y en el código el nombre de las funciones que leen y escriben los distintos tipos de datos.

  Escritura Lectura
Un carácter writeChar readChar
Un entero writeInt readInt
Un número decimal writeDouble readDouble
Un string writeChars readLine

Veamos el código que escribe los datos a un archivo pedido.txt en disco

  1. Se parte de los datos que se guardan en los arrays  denominados descripciones, unidades y precios
  2. Se crea un objeto de la clase DataOutputStream vinculándolo a un un objeto FileOutputStream para escribir en un archivo en disco denominado pedido.txt..
  3. Se escribe en el flujo de salida los distintos datos llamando a las distintas versiones de la función writeXXX según el tipo de dato (segunda columna de la tabla).
  4. Se cierra el flujo de salida, llamando a su función miembro close.
  double[] precios={1350, 400, 890, 6200, 8730};
  int[] unidades={5, 7, 12, 8, 30};
  String[] descripciones={"paquetes de papel", "lápices", "bolígrafos", "carteras", "mesas"};

  DataOutputStream salida=new DataOutputStream(new FileOutputStream("pedido.txt"));
  for (int i=0; i<precios.length; i ++) {
      salida.writeChars(descripciones[i]);
      salida.writeChar('\n');
      salida.writeInt(unidades[i]);
      salida.writeChar('\t');
      salida.writeDouble(precios[i]);
  }
  salida.close();

Para leer bien los datos, el string ha de separase del siguiente dato con un carácter nueva línea '\n'. Esto no es necesario si el string se escribe en el último lugar, después de los números. Por otra parte, el carácter tabulador como separador no es estrictamente necesario.

Veamos el código que lee los datos a un archivo pedido.txt en disco

  1. Se crea un objeto de la clase DataInputStream vinculándolo a un un objeto FileInputStream para leer en un archivo en disco denominado pedido.txt..
  2. Se lee el flujo de entrada los distintos datos en el mismo orden en el que han sido escritos, llamando a las distintas versiones de la función readXXX según el tipo de dato (tercera columna de la tabla).
  3. Se guardan los datos leídos en memoria  en las variables denominadas descripcion, unidad y precio y se usan para distintos propósitos
  4. Se cierra el flujo de entrada, llamando a su función miembro close.
  double precio;
  int unidad;
  String descripcion;
  double total=0.0;

  DataInputStream entrada=new DataInputStream(new FileInputStream("pedido.txt"));
  try {
      while ((descripcion=entrada.readLine())!=null) {
          unidad=entrada.readInt();
          entrada.readChar();       //lee el carácter tabulador
          precio=entrada.readDouble();
          System.out.println("has pedido "+unidad+" "+descripcion+" a "+precio+" pts.");
          total=total+unidad*precio;
      }
  }catch (EOFException e) {}
  System.out.println("por un TOTAL de: "+total+" pts.");
  entrada.close();

Como vemos en esta porción de código, según se van leyendo los datos del archivo, se imprimen y se calcula el precio total del pedido.

        System.out.println("has pedido "+unidad+" "+descripcion+" a "+precio+" pts.");
        total=total+unidad*precio;

El final del archivo

El final del archivo se detecta cuando la función readLine devuelve null. Alternativamente, cuando se alcanza el final del archivo se produce una excepción del tipo EOFException. Podemos comprobarlo del siguiente modo

Si escribimos la siguiente porción de código

        try {
            while(true){
                descripcion=entrada.readLine();
                unidad=entrada.readInt();
                entrada.readChar();       //lee el carácter tabulador
                precio=entrada.readDouble();
                System.out.println("has pedido "+unidad+" "+descripcion+" a "+precio+" pts.");
                total=total+unidad*precio;
            }
        }catch (EOFException e) {
            System.out.println("Excepción cuando se alcanza el final del archivo");
        } 

Cuando se alcanza el final del archivo se produce una excepción del tipo EOFException que interrumpe la ejecución del bucle indefinido al ser capturada por el correspondiente bloque catch, el cual imprime en la pantalla el mensaje "Excepción cuando se alcanza el final del archivo".

Si escribimos la siguiente porción de código

        try {
            while ((descripcion=entrada.readLine())!=null) {
                unidad=entrada.readInt();
                entrada.readChar();       //lee el carácter tabulador
                precio=entrada.readDouble();
                System.out.println("has pedido "+unidad+" "+descripcion+" a "+precio+" pts.");
                total=total+unidad*precio;
            }
            System.out.println("Final del archivo");
        }catch (EOFException e) {
            System.out.println("Excepción cuando se alcanza el final del archivo");
        } 

Se imprime "Final de archivo" ya que cuando readLine toma el valor null (no hay más que leer) se sale del bucle while, y por tanto, no se lanza ninguna excepción.