Professional Documents
Culture Documents
GUIA DE PRCTICA 9
ASIGNATURA TEMA PROFESOR ALUMNO FECHA CICLO TURNO SEMESTRE 1. OBJETIVOS Que el estudiante: Use y manipule los mecanismos de persistencia para registrar la informacin en java Algortmica II PERSISTENCIA Carlos A. Ruiz De La Cruz Melo
2008-1
2. INTRODUCCION TEORICA
Normalmente, cuando se codifica un programa, se hace con la intencin de que el programa pueda interactuar con los usuarios del mismo, es decir, que el usuario pueda pedirle que realice determinada tarea, suministrndole datos con los que debe llevar a cabo la tarea solicitada. Se espera que el programa los manipule de alguna forma, proporcionando una respuesta a lo solicitado. Por otra parte, en muchas ocasiones interesa que el programa guarde los datos que se le han introducido, de forma que al finalizar el proceso, los datos no se pierdan y puedan ser recuperados en una sesin posterior. La forma habitual de hacer esto es mediante la utilizacin de dispositivos de almacenamiento secundario o externo (normalmente un disco). Se llama persistencia a la capacidad de una entidad de trascender el tiempo o el espacio. En la programacin previa al paradigma de objetos estaba representada con la entrada y salida de datos. Es un concepto importante, pues permite que un objeto pueda ser usado en diferentes momentos
2.1. Flujos
El modelo ms sencillo de un algoritmo consiste en tres conexiones: datos de entrada, procesamiento y datos de salida. Entrada y salida ( E / S ) es un aspecto fundamental en la computacin. La computadora no sera muy til si no pudiera recibir datos del mundo exterior y presentar los datos computados. En esta seccin se describe como Java , a travs de java.io y java.nio, y otros paquetes relacionados , proporciona clases independientes para manipular archivos y flujos ( streams ).
import java.io.*; public class HolaOscar { public static void main(String[] args) throws IOException { InputStreamReader lector = new InputStreamReader(System.in); BufferedReader entrada = new BufferedReader(lector); System.out.print("Cual es tu nombre? "); String nombre = entrada.readLine(); System.out.println("Hola " + nombre + "!"); } }// fin de la clase HolaOscar
La salida del programa al ejecutarlo con el comando java HolaOscar es: Da tu nombre: Oscarin Hola, Oscarin! En la siguiente figura vemos el proceso de tomar los datos del flujo estndar de entrada System.in asociado al teclado con la creacin del objeto lector de la clase InputStreamReader . Luego con el objeto lector lo utilizamos como argumento del constructor de un objeto entrada de la clase BufferReader , el cual tiene mtodos como readLine() , para leer el conjunto de bytes del buffer hasta el final de la lnea. Finalmente utilizamos el mtodo println() de System.out que esta asociado al flujo estndar de salida para presentar los datos por la consola o monitor.
especficos. Tambin observe que el mtodo main() se esta manejando la excepcin IOException , para preveer algn tipo de error en el flujo de entrada o salida. ver el ejemplo: /** * Ejemplo: programa de flujos (streams) * que lee el valor del radio desde el teclado y calcula * el rea del circulo. La cadena del nmero see lee * con un flujo de entrada que luego es convertido a * formato de nmero de tipo double con doubleValue() * de la clase wrapper Double . El programa calcula el * rea del circulo en base al radio dado y presenta el * resultado por pantalla. * @author Oscar A. Gonzlez Bustamante * @version 1.0 * Archivo: AreaCirculo.java */ import java.io.*; public class AreaCirculo{ public static void main(String[] args) throws IOException { InputStreamReader lector = new InputStreamReader(System.in); BufferedReader entrada = new BufferedReader(lector); System.out.print("Introduce valor del radio: "); String texto = entrada.readLine(); Double x = new Double(texto); double r = x.doubleValue(); System.out.println("El area de un circulo de radio "+ r ); double area = r*r*Math.PI; System.out.println(" es " + area); } }// fin de la clase AreaCirculo Para correr el programa hay que ejecutar la sentencia java AreaCirculo y presenta los siguientes resultados si se le da como radio el valor de 10. Introduce valor del radio: 10 El area de un circulo de radio 10.0 es 314.1592653589793
o OutputStream
Algunas de estas clases van a aparecer junto con algunos de sus mtodos, en los ejemplos que veremos mas adelante.
2.1.4 Flujos de bytes Para los ejemplos siguientes, supondremos que los objetos de tipo InputStream y OutputStream nos vienen dados, sin preocuparnos de como han sido creados (de hecho, las clases mencionadas ya habamos dicho que son clases abstractas que y no pueden ser instanciadas , as que son la base de otras clases concretas de donde si podemos instanciar objetos ). public abstract class InputStream extends Object Lectura de bytes individuales: Se logra mediante cdigo como:
InputStream is= ...; int b = is.read();
As podemos obtener el siguiente byte del InputStream. Hay que darse cuenta que el byte (8 bits) se devuelve como un dato de tipo int (32 bits), con un valor entre 0 y 255. En caso de que se haya alcanzado el final del archivo, el mtodo read() devuelve un valor de -1. Lectura de varios bytes. Primero se crea un arreglo unidimensional del tamao adecuado. El tamao de este arreglo es lo que indica al mtodo read() cuntos bytes debe leer como mximo. El siguiente ejemplo de fragmento de cdigo lee 1024 bytes de un flujo de entrada.
byte[] = miArreglo = new byte[1024]; // declaramos el arreglo.
La variable lee almacena el nmero de bytes que se han ledo en realidad. Si se llega al final del archivo, devuelve el valor de -1. No hay garanta de leer exactamente el nmero de bytes especificado, porque puede ser menor debido a que estamos leyendo de un archivo que se ha acabado, porque los datos de una conexin de red tardan en llegar, o cualquier otra causa. De cualquier forma, cuando el mtodo read() devuelva un valor distinto de -1 podemos seguir leyendo mediante sucesivas llamadas a read(). Veamos el siguiente ejemplo que muestra el uso del mtodo read() para leer bloques de bytes.
/** * Ejemplo: programa de flujos (streams) * que lee el flujos de bytes. Las cadenas a leer se * almacenan en los arreglos de bytes buffer1 y buffer2. * Ambos tiene un tamao especfico de 20 bytes y * son ledos con el mtodo read(). Luego instanciamos * dos objetos de la clase String con dichos buffers. * Finalmente los enviamos por System.out.println() a * la pantalla o consola de salida, y usamos el mtodo * trim() para eliminar los espacios blancos o vacos. * @author Oscar A. Gonzlez Bustamante * @version 1.0 * Archivo: EscribeNombres.java */ public class EscribeNombres { public static void main(String[] args) { final int LON = 20 ; byte[] buffer1 = new byte[LON]; System.out.print("Introduce tu apellido: "); try { System.in.read(buffer1, 0, LON) ; } catch (Exception e) {} String apellido = new String(buffer1) ; byte[] buffer2 = new byte[LON]; System.out.print("Introduce tu nombre: "); try { System.in.read(buffer2, 0, LON) ; } catch (Exception e) {} String nombre = new String(buffer2) ; System.out.println("Hola , " + nombre.trim() + " " + apellido.trim()); } } // fin de la clase EscribeNombres La salida del programa al ejecutarlo con el comando java EscribeNombres es: Introduce tu apellido: GONZALEZ Introduce tu nombre: OSCAR Hola , OSCAR GONZALEZ Cerrar el flujo de entrada. Cuando ya no necesitamos leer datos de un flujo de entrada, se tienen que liberar los recursos reservados mediante el mtodo close(). Si no cerramos el InputStream explcitamente, el flujo asociado se cierra cuando se destruye el objeto. Escritura de bytes individuales. La clase OutputStream dispone de varios mtodos write(). Ejemplo:
OutputStream os = ..; int dato = 777; os.write(dato); Como en el caso del mtodo read() de la clase InputStream , el mtodo write() recibe un byte dentro de una variable de tipo int (32 bits). Escritura de varios bytes. El cdigo siguiente es muy ilustrativo. byte[] vector = { 65, 66, 67, 68, 69}; OutputStream os = ...; os.write(vector); // escribe los bytes 65, 66,67,68,69 os.write(vector,1,3); // escribe los bytes 66,67,68
try { InputStream is= ..; while ( ... ) { // Leemos y procesamos datos involucrados con los flujos } }catch(IOException ioe) { System.err.println("Hubo un error al abrir el flujo tal y tal ... "); ioe.printStackTrace(); } En programas pequeos en los que no se quiera complicarse la existencia con estructuras de ste tipo, se puede tomar el camino alternativo de mandar la excepcin "hacia arriba". Por ejemplo: public static void main(String[] args) throws IOException { // programa creado por un programador flojo } El siguiente programa calcula el rea de un tringulo, y hace uso del manejo de excepciones para los flujos de entrada de tipo java.io.IOException en el mtodo lee_doble() . Si al compilar el programa le manda un warning de que el mtodo readLine() esta desaprobado ( deprecated ), no se preocupe mucho por eso, el programa correr, es solo una advertencia del compilador de Java que le invita a ud. a utilizar algn otro mtodo ms actualizado para dicho fin.
/** * Ejemplo: programa de flujos (streams) * que lee el un flujo de datos por el teclado * y lo convierte a un valor de tipo double. * El programa utiliza manejo de excepciones * de tipo java.io.IOException. * @author Oscar A. Gonzlez Bustamante * @version 1.0 * Archivo: AreaTriangulo.java */ import java.io.DataInputStream; class AreaTriangulo{ static double lee_doble(String msj) { DataInputStream stream = new DataInputStream(System.in); String strng; double aux; // escriba una linea para leer desde el teclado. try { System.out.print(msj); strng = stream.readLine(); } catch ( java.io.IOException e ) { strng = "0.0"; } // tratando de convertir este valor a un valor de tipo double try { aux = Double.valueOf(strng).doubleValue(); } catch ( java.lang.NumberFormatException e) { aux = 0.0; } return aux; } public static void main (String args[] ) { double a,b,c; double s,p; System.out.println("Calcular Area de un triangulo"); a = lee_doble("Dame lado a: "); b = lee_doble("Dame lado b: "); c = lee_doble("Dame lado c: "); System.out.println("a= "+ a + " b = " + b + " c= " + c); p = ( a + b + c ) / 2.0; System.out.println("p= " + p); s = Math.sqrt( p*(p-a) * (p-b) * (p-c) ); System.out.println("Area = " + s ); System.out.println("fin del programa");
} } // fin de la clase AreaTriangulo La salida del programa al ejecutarlo con el comando java AreaTriangulo es: Calcular Area de un triangulo Dame lado a: 30 Dame lado b: 40 Dame lado c: 50 a= 30.0 b = 40.0 c= 50.0 p= 60.0 Area = 600.0 fin del programa
else { // El archivo no existe } Se puede obtener ms informacin de un objeto de la clase File, como , el tamao del archivo, si se puede leer el archivo, si se puede escribir en el archivo, si se ha borrado con xito el archivo, si se puede borrar, el nombre de la carpeta donde se encuentra el archivo, etc. Veamos los siguientes fragmentos de cdigo : File f = new File("c:\\cursojava\\elarchivo.txt"); long = f.length(); // tamao del archivo boolean lectura = f.canRead(); // Podemos leer el archivo ? boolean escritura = f.canWrite(); // Podemos escribir el archivo ? if ( f.delete()) { // archivo borrado con xito } else { // el archivo no se ha podido borrrar } String nombre = f.getName(); // Nombre (sin carpeta) del archivo String dir = f.getParent(); // Directorio o carpeta del archivo if ( f.isDirectory() ) { // Es un directorio } else { // No es un directorio } if ( f.isFile() ) { // es un archivo normal } else { // no es un archivo normal } long modificado = f.lastModified(); // Fecha ltima de modificacin o actualizacin if ( f.renameTo( new File("c:\\cursojava\\otroArchivo.txt"))) { // Nombre de archivo modificado } else { // nombre de archivo no modificado } La clase File, tambin nos permite manejar carpetas. Los siguientes fragmentos de cdigo que se muestran a continuacin ejemplifican como se puede trabajar con carpetas o directorios mediante la clase File. File f = new File ("c:\\cursojava");
10
String[] lista = f.list(); // obtenemos la lista de archivos for ( int i=0; i < lista.length; i++) // los imprimimos System.out.println("Archivo n " + i + ":" + lista[i]); File t = new File("c:\\cursojava\\ejemplos" ); if ( t.mkdir() ) { // Se ha creado un directorio ejemplos sobre c:\cursojava previamente existente } else { // no se pudo crear el directorio } File w = new File("c:\\cursojava\\alumnitos\\aplicados\\estudiosos\\deJava");
if ( w.mkdirs() ) { /* Se ha creado el directorio deJava junto con los directorios intermedios necesarios. */ } else { /* No se pudo crear el directorio */ }
11
long modificado; try { File f = new File(ruta+archi); prhr('-',80);prhr('\n',1); if (f.exists() ) { // mas datos sobre el archivo System.out.println("\tArchivo : "+archi+ " encontrado con xito en: "+ ruta); System.out.println("\tTamao del archivo(compararlo al final): " + f.length() + " Bytes"); lectura = f.canRead(); // se puede leer el archivo ? escritura = f.canWrite(); // se puede escribir el archivo? nombre = f.getName(); /* Nombre (sin directorio) del archivo */ directorio = f.getParent(); /* Directorio del archivo */ modificado = f.lastModified(); /* Fecha de ltima modificacin */ Date d = new Date(modificado); if (lectura && escritura ) System.out.println("\tEs una archivo de lectura y escritura\n"); else if( lectura && !escritura) System.out.println("\tEs un archivo de solo lectura\n"); else if( !lectura && !escritura) System.out.println("\tEs un archivo que no se puede leer ni escribir\n"); else if( escritura ) System.out.println("\tEs un archivo de escritura\n"); System.out.println("Nombre del archivo: " + nombre); System.out.println("Nombre del directorio o carpeta del archivo : " + directorio); System.out.println("Fecha de ltima modificacin : "+ d); } else System.out.println(" El archivo: " + archi + " no existe en : " + ruta); prhr('-',80);prhr('\n',1); FileInputStream fis = new FileInputStream(f); while(( parcial=fis.read())!=-1) { total+= parcial; tamao++; car = (char)parcial; System.out.print(car); } System.out.print("\n"); fis.close(); } catch (FileNotFoundException fnfe) { /* Archivo no encontrado */
12
System.err.println("Archivo no encontrado, Error: " + fnfe.getMessage()); } catch (IOException ioe) { /* Error al leer */ System.err.println("Error al leer el archivo, Error: " + ioe.getMessage()); } finally { prhr('-',60);prhr('\n',1); System.out.println("\tEl tamao del archivo:("+archi+":"+tamao+" Bytes)"); } System.out.println("Fin del programa"); } //fin del main() } //fin de la clase FlujoArchivos2 La salida del programa al ejecutarlo con el comando java FlujoArchivos2 y que muestra el archivo IncrementoDecremento.java que se encuentra en la carpeta C:\j2sdk141\ejemplos\ es:
-------------------------------------------------------------------------------Archivo : IncrementoDecremento.java encontrado con xito en: C:\j2sdk141\ejemplos\ Tamao del archivo(compararlo al final): 604 Bytes Es una archivo de lectura y escritura Nombre del archivo: IncrementoDecremento.java Nombre del directorio o carpeta del archivo : C:\j2sdk141\ejemplos Fecha de ltima modificacin : Fri Aug 10 20:17:24 GMT-06:00 2001 -------------------------------------------------------------------------------import java.io.*; public class IncrementoDecremento { public static void main(String[] args) { char c = 'R'; byte j = 127; short k = 32767; System.out.println("c = " + c); ++c; System.out.println("c = " + c); ++c; System.out.println("c = " + c); System.out.println("j = " + j); --j; System.out.println("j = " + j); ++j; System.out.println("j = " + j); ++j; System.out.println("j = " + j); System.out.println("k = " + k); k -= 4; System.out.println("k = " + k); k += 5; System.out.println("k = " + k); } }//?>
-----------------------------------------------------------El tamao del archivo:(IncrementoDecremento.java:604 Bytes) Fin del programa
13
El segundo ejemplo de la clase File muestra el uso de algunos de sus mtodos para manejo de carpetas o directorios: /** * Programa de java que ejemplifica el uso * de la clase File para demostrar * el manejo de carpetas o directorios * @autor Oscar A. Gonzlez Bustamante * @version 1.0 * Archivo: FlujoArchivos3.java */ import java.io.*; import java.util.Date; public class FlujoArchivos3 { static String ruta = "C:\\j2sdk141\\ejemplos\\E-S\\"; static String[] lista; static void prhr(char c, int lim) { for(int i=0; i<lim ; i++) System.out.print(c); } static void prln(String msg) { System.out.println(msg); } static void pr(String msg) { System.out.print(msg); } public static void main(String[] argumentos) { try { File f = new File(ruta); prhr('-',80);prhr('\n',1); if (f.exists() ) { lista = f.list(); /* Obtenemos la lista de archivos */ for (int i=0; i<lista.length; i++) /* los imprimimos */ prln("Archivo n\u00B0 "+(i+1)+": " + lista[i]); } else System.out.println(" El directorio: " + ruta + " no existe "); } catch (Exception e) { /* directorio no encontrado */ System.err.println("Directorio no encontrado, Error: " + e.getMessage()); } finally { prhr('-',60);prhr('\n',1); } System.out.println("Fin del programa"); } // fin del main } //fin de la clase FlujoArchivos3 La salida del programa que muestra el contenido de archivos de la carpeta de mi computadora C:\\j2sdk141\\ejemplos\\E-S\\ , al ejecutarlo con el comando java FlujoArchivos3 es:
--------------------------------------------------------------------------------
14
Archivo n 1: Alumnitos.txt Archivo n 2: Alumno.class Archivo n 3: alumnosxsqlserver2000.sql Archivo n 4: ArchiEnt.txt Archivo n 5: ArchivoEnt.class Archivo n 6: ArchivoSal.class Archivo n 7: ArchivoSal.txt Archivo n 8: classes Archivo n 9: Copy.class Archivo n 10: Copy.java Archivo n 11: E-ASAjava.doc Archivo n 12: E-SenJava.doc Archivo n 13: entrada.txt Archivo n 14: ENTSAL.bak Archivo n 15: ENTSAL.jde Archivo n 16: Escribe.class Archivo n 17: EscribeNombres.class Archivo n 18: EscribeNombres.java Archivo n 19: EsencialJDBC.class Archivo n 20: EsencialJDBC.java Archivo n 21: Estudiantes.txt Archivo n 22: Evaluador.class Archivo n 23: Evaluador.java Archivo n 24: EvaluadorArchi.class Archivo n 25: EvaluadorArchi.java Archivo n 26: EvaluadorArchivos2.class Archivo n 27: EvaluadorArchivos2.java Archivo n 28: EvaluadorBD2.class Archivo n 29: EvaluadorBD2.java Archivo n 30: EvaluadorBD3.class Archivo n 31: EvaluadorBD3.java Archivo n 32: Flujo1.java Archivo n 33: FlujoArchivos1.java Archivo n 34: FlujoArchivos2.class Archivo n 35: FlujoArchivos2.java Archivo n 36: FlujoArchivos3.class Archivo n 37: FlujoArchivos3.java Archivo n 38: Mi2doAccesoJDBC.class Archivo n 39: MiAccesoJDBC.class Archivo n 40: MS-DOS.LNK Archivo n 41: Persona.class Archivo n 42: PrintNames.class Archivo n 43: PrintNames.java Archivo n 44: salida.txt Archivo n 45: src Archivo n 46: Sumatorias.class Archivo n 47: Sumatorias.java Archivo n 48: Smbolo del sistema.lnk Archivo n 49: tablaALUMNOSXsqlserver2000.sql -----------------------------------------------------------Fin del programa
15
} fos.close(); Otro ejemplo puede ser el comando copy de MS-DOS: /** * Ejemplo: programa de flujos (streams) * que ejemplifica el uso de las clases * FileInputStream y FileOutputStream para * programar el comando copy de MS-DOS * El programa utiliza manejo de excepciones * de tipo java.io.IOException. * @author Oscar A. Gonzlez Bustamante * @version 1.0 * Archivo: Copy.java */ import java.io.*; class Copy { public static void main(String[] args) { String origen = args[0]; String destino = args[1]; byte buffer[] = new byte[1024]; int cuenta; try { FileInputStream fis = new FileInputStream(origen); FileOutputStream fos = new FileOutputStream(destino); while((cuenta=fis.read(buffer))>0) fos.write(buffer,0,cuenta); } catch(IOException ioe) { System.err.println("Se ha producido un error"); ioe.printStackTrace(); } } // fin del mtodo main() } // fin de la clase Copy Si ejecutamos el programa Copy con el comando : java Copy c:\temporal\archivo1.txt "c:\Mis Documentos\archivo2.txt" El programa copiar el contenido de un archivo en el otro, en bloques de 1024 bytes con el mtodo read() leyendo del archivo origen , al archivo destino con el mtodo write(). La ruta y archivo de origen y destino son los argumentos del mtodo main() . Por supuesto se deja al lector de este material, agregar el cdigo de cerrar los flujos de entrada fis y salida fos con el mtodo close() . Cabe sealar que si el archivo destino ya existe, ser borrado. Si el archivo origen no existe, el catch del programa nos notificar y volacar en pantalla el contenido de la pila de llamadas.
Los programas que se han visto hasta ahora solo escriben bytes en un flujo de datos. A pesar de que con estas tcnicas podramos leer y escribir cualquier cosa en un archivo, esta forma de trabajar es relativamente pesada, ya que cada vez que quisiramos escribir, por ejemplo, un entero de 32 bits en un archivo, tendramos que dividir los 32 bits en cuatro paquetes de 8 bits cada uno, e ir transmitindolos a travs de flujo de datos. Para leer ese dato, el proceso sera el inverso; leer cuatro bytes del flujo y combinarlos para obtener el nmero de 32 bits. Como veremos, el paquete java.io nos proporciona varias herramientas para facilitarnos este trabajo. La clase DataOutputStream La clase DataOutputStream , es una extensin de la clase OutputStream , y aade a sta ltima la posibilidad de escribir datos "complejos" en un flujo de salida. Cuando hablamos de datos "complejos", en realidad nos referimos a tipo de datos primitivos, pero no restringidos nicamente a bytes y a matrices de bytes, como en el caso de OutputStream . Mediante la clase DataOutputStream podemos escribir datos de tipo int, float, double, char, etc. Adems podemos escribir algunos objetos, como datos de tipo String , en una gran cantidad de formatos. La forma general de trabajar con objetos de tipo DataOutputStream es la siguiente: obtenemos un objeto OutputStream (cuyo origen puede ser cualquiera, un archivo, un socket, una matriz en memoria, la salida estndar, etc.) y lo "envolvemos" en un objeto DataOutputStream , de forma que podamos usar la interfaz que nos proporciona este ltimo. Para crear este DataOutputStream , le pasamos como parmetros el OutputStream a su constructor. Cada vez escribamos un dato "complejo" en un objeto DataOutputStream . Este lo traducir a bytes individuales, y los escribir en el OutputStream subyacente, sin que nosotros tengamos que preocuparnos de la forma en que lo hace. Veamos algunos ejemplos: OutputStream os = ... ; int a = -7; float b= 3.42552; double c = 747.8839; dos.writeInt(a); // Escribimos un entero en el stream (4 bytes) dos.writeFloat( b ); // Escribimos un nmero de precisin simple (4 bytes) dos.writeDouble( c ); // Escribimos un nmero de precisin doble (8 bytes) dos.close(); os.close(); Los nombres de los mtodos usados son bastante descriptivos por s mismo. En la documentacin del SDK de Java podemos encontrar otros mtodos, uno para cada tipo de dato primitivo: writeBoolean(), writeByte() , writeChar() , writeLong() y writeShort(). // Creamos el flujo de salida
17
Si seguimos explorando el SDK, descubriremos algunos mtodos de los que an no hemos hablado; writeBytes() ; writeChars() y writeUTF() . Estos tres mtodos reciben como parmetros un objeto de tipo String , y lo escriben en el OutputStream subyacente usando diferentes formatos. writeBytes() descompone la cadena de texto en bytes individuales (obtiene su cdigo ASCII) y los escribe en el flujo de salida. Si la cadena consta de n letras, escribe n bytes, sin aadir ningn delimitador ni de principio ni de fin de cadena. writeChars() descompone la cadena de texto en chars individuales (obtiene su cdigo Unicode) y los escribe en el flujo de salida. Si la cadena consta de n letras, escribe n valores char, sin aadir ningn delimitador ni de principio ni de fin de cadena. writeUTF() escribe la cadena en un formato conocido como UTF-8. Este formato incluye informacin sobre la longitud exacta de la cadena. La conclusin importante que debemos extraer de estos tres ltimos mtodos es que slo el ltimo nos permite recuperar la cadena con facilidad. Los otros dos mtodos no incluyen informacin sobre la longitud de la cadena, por lo que si otro programa necesita leer los datos que nosotros hemos escrito, es necesario conocer con anticipacin la longitud de la cadena. Si no sabemos esto, es imposible saber el nmero de bytes o de valores char que debemos leer. Un fragmento de cdigo ejemplo de utilizacin de estos mtodos es: Strng cadena1 = "Me voy a descomponer en una cadena de texto de bytes individuales"; String cadena2 = "Me voy a descomponer en una cadena de texto de chars individuales"; String cadena3 = "Me voy a descomponer en una cadena de texto en formato UTF-8 "; dos.writeBytes(cadena1); dos.writeChars(cadena2): dos.writeUTF(cadena3);
18
y = dis.readFloat(); z = dis.readDouble(); dis.close(); is.close(); Qu pasa si deseamos leer las cadenas de texto que hemos escrito?. Es inmediato leer la cadena escrita en formato UTF. En cambio, leer las otras dos cadenas nos va a costar ms trabajo, ya que debemos leer los bytes o los chars individuales, juntarlos de forma adecuada y construir la cadena resultante. En este caso usaremos un truco , ya que sabemos que las cadenas cadena1 y cadena2 tienen una longitud de 65 letras exactamente. En una situacin normal, puede que no tengamos esta informacin. int tam = 65; // Aplicamos el truco InputStream is =...; //creamos el flujo de entrada DataInputStream dis = new DataInputStream( is ); byte miNuevoArray[] = new byte [ tam ]; dis.readFully(miNuevaArray); /* Este mtodo es nuevo */ String cadenaConvertida = new String(miNuevaArray,0=; // Ahora tenemos que leer un montn de caracteres char de (16 bits) // que forman el siguiente String escrito. // Hay que hacer un bucle para ir leyendo los caracteres uno por uno char otroArrayMas[] = new char[tam]: for( int n = 0 ; n < tam ; n++ ) otroArrayMas[ s ] = dis.readChar(); String otraCadenaconvertida = new String( otroArrayMas ); // Solo resta leer el String en formato UTF-8 // Unicamente con llamar a readUTF(), ya que la longitud // del String est indicada en el propio archivo. String ultimaCadena = dis.readUTF(); En el ejemplo anterior hemos usado un mtodo nuevo. DataInputStream.readFully( byte[] ) , que es bsicamente equivalente a InputStream.read(byte[]) , con la nica diferencia de que no retorna hasta que hayan sido ledos exactamente el nmero de bytes que caben en la matriz. Es fcil apreciar las ventajas de usar los mtodos writeUTF() y readUTF() .
19
int tam = 40; byte[] buffer = new byte[ tam ]; for( int n = 0 ; n < tam ; n++ ) buffer[n] = n; ByteArrayInputStream bais = new ByteArrayInputStream( buffer ); int c: while( ( c = bais.read() ) != -1 ) ... La clase ByteArrayPutputStream es otra del mismo tipo muy til, ya que por medio de esta podemos escribir datos en un flujo, sabiendo que estos datos se almacenan internamente en una matriz de bytes. Esta matriz crece dinmicamente a medida que escribimos datos en ella. Una vez escritos los datos, podemos acceder a la matriz de bytes mediante el mtodo toByteArray(), que nos devuelve una copia de la matriz original. Veamos el siguiente fragmento de cdigo de ejemplo: ByteArrayOutputStream baos = new ByteArrayOutputStream(): boolean condicion = false; while( condicion ) { int dato = ; baos write(dato); condicion = ; } byte[] bufferSalida = baos.toByteArray(); Una vez ejecutado el cdigo anterior obtenemos una matriz de bytes con todos los datos que se han ido introduciendo en la iteracin del bucle. /*Mientras leamos algo de buffer*/ System.out.println( " Se ha ledo el valor: " + c );
20
Informacin general de rendimiento del grupo de estudiantes. Mxima Calificacin ALumno Promedio Mnima Calificacin Alumno Promedio Varianza de los promedios
Solucin: La clase EvaluadorArchivos tiene el mtodo main() que arranca todo el proceso, y en l estn los nombres de los archivos entrada.txt y salida.txt para el manejo de los datos. Tambin se leen todos los datos del archivo entrada.txt para asignrselos al arreglo p de la clase Alumnos en el bucle while de la lnea 116 a la 119. Despus se invocan a algunos mtodos estticos de clase para el clculo de los datos estadsticos. As, el mtodo esttico de clase PromediosGenerales(Alumno z[]) devuelve el promedio de cada alumno y recibe el arreglo de la clase Alumno . El mtodo maxYminCalif(Alumno w[]) hace el trabajo de obtener que alumnos obtuvieron la mxima y mnima calificacin y los imprime, y finalmente el mtodo varianzaPromedios(Alumno v[],double media) calcula la varianza, en base a la media que se le envia como argumento.
1. /** 2. * Programa de java que ejemplifica el uso 3. * de las clases DataInputStream y DataOutputStream 4. * para ensearte a usar datos con formato en archivos. 5. * @autor Oscar A. Gonzlez Bustamante 6. * @version 1.0 7. * Archivo: EvaluadorArchivos2.java 8. */ 9. 10. public class EvaluadorArchivos2 { 11. 12. static void imprime( Alumno x[] ) { 13. final int band=1; 14. 15. if( band ==1) 16. System.out.println("Id\tNombre\tApellidos\tCargo\tTrato\tWindows\tWord\tExcel\tPromedio\tCalificacion"); 17. 18. for (int i=0; i< x.length; i++) { 19. System.out.println(""+x[i].id + "\t" + Profesor: Carlos A. Ruiz De La Cruz Melo 21
20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69.
x[i].getCalificacion() + "\t" ); Escribe.ponRaya(100,"-"); } } static double PromediosGenerales(Alumno z[]) { double sumaWindows=0.0, sumaWord=0.0, sumaExcel= 0.0, sumaGrupo= 0.0; double promWindows=0.0, promWord=0.0, promExcel= 0.0, promGrupo= 0.0; System.out.println(); Escribe.ponRaya(100,"="); System.out.println("Informacin general del rendimiento del grupo de estudiantes"); Escribe.ponRaya(100,"="); for (int i=0; i< z.length; i++) { sumaWindows = sumaWindows + z[i].getExamen(1); sumaWord = sumaWord + z[i].getExamen(2); sumaExcel = sumaExcel + z[i].getExamen(3); sumaGrupo = sumaGrupo + z[i].getPromedio(); } promWindows = sumaWindows / z.length; promWord = sumaWord / z.length; promExcel = sumaExcel / z.length; promGrupo = sumaGrupo / z.length; System.out.println("\tPromedio de Windows:"+ promWindows + "\n" + "\tPromedio de Word: " + promWord "\tPromedio de Excel: " + promExcel "\tPromedio del Grupo: " + promGrupo); System.out.println(""); return promGrupo; } public static void maxYminCalif(Alumno w[]) { double maxima=0.0, minima=0.0; int burro= 0, estrellita= 0; System.out.println(); maxima = w[0].getPromedio(); + "\n" + + "\n" +
22
70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119.
minima = w[0].getPromedio(); for(int i=1; i< w.length; i++){ if ( maxima < w[i].getPromedio() ) {maxima = w[i].getPromedio(); estrellita = i; } if ( minima > w[i].getPromedio() ) {minima = w[i].getPromedio(); burro = i; } } Escribe.ponRaya(40,"-"); System.out.println("\tMaxima Calificacion:" "\n\tPromedio:" + maxima); System.out.println(); System.out.println("\tMinima Calificacion:" "\n\tPromedio:" + minima); } public static void varianzaPromedios(Alumno v[],double media) { double ds=0.0, varianza = 0.0; for (int i=0; i < v.length; i++) { ds = ds + Math.pow(media - v[i].getPromedio(),2); } ds = ds/ v.length; varianza = Math.sqrt(ds); Escribe.ponRaya(40,"-"); System.out.println("\tVarianza de los promedios:" + varianza); } public static void main( String args[] ) { String[] archivos = { new String("salida.txt"), new String("entrada.txt") }; String archient = archivos[1]; String archisal = archivos[0]; double lamedia = 0.0; Alumno p[] = new Alumno[9]; // Crea un flujo de entrada ArchivoEnt archivo_secu = new ArchivoEnt(archient); + "\n\tAlumno:" + w[burro].nombre + " " + w[burro].apellidos + + "\n\tAlumno:" + w[estrellita].nombre + " " + w[estrellita].apellidos +
// Mientras no se encuentre el final del archivo sigue leyendo int i=0; while (i<p.length) { p[i] = archivo_secu.leer(); i++; }
23
120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150.
archivo_secu.cerrar();
imprime(p); lamedia=PromediosGenerales(p); maxYminCalif(p); varianzaPromedios(p,lamedia); //parte dedicada a crear los datos y guardarlos en un archivo de salida // hay que quitarle los comentarios si no existe el archivo con formato de entrada /* p[0] = new Alumno(1,"Davolio","Nancy","Representante de Ventas","Srta.",8.00,8.19,9.04); p[1] = new Alumno(2,"Fuller","Andrew","Vicepresidente comercial","Dr.",8.00,9.00,6.00); p[2] = new Alumno(3,"Leverling","Janet","Representante de Ventas","Srta.",8.00,8.00,8.00); p[3] = new Alumno(4,"Peacock","Margaret","Representante de Ventas","Sra.",8.32,8.00,8.00); p[4] = new Alumno(5,"Buchanan","Steven","Gerente de Ventas","Sr.",10.0 ,8.00 ,10.0); p[5] = new Alumno(6,"Suyama","Michael","Representante de Ventas","Sr.",8.00,5.00,8.00); p[6] = new Alumno(7,"King","Robert","Representante de Ventas","Sr.",8.91,8.00,9.00); p[7] = new Alumno(8,"Callahan","Laura","Cordinador ventas interno","Srta.",8.00,1.14,5.57); p[8] = new Alumno(9,"Dodsworth","Anne","Representante de ventas","Srta.",8.00,7.50,8.00); ArchivoSal archi_secu = new ArchivoSal(archisal); for ( int i=0; i<p.length; i++) { archi_secu.insertar(p[i]); } archi_secu.cerrar(); */ } // fin del main() } // fin de EvaluadorArchivos2
Al ejecutar este programa con el comando java EvaluadorArchivos2 da los siguientes resultados:
Id Nombre Apellidos Cargo Trato Windows Word Excel Promedio Calificacion 1 Davolio Nancy Representante de Ventas 8.0 8.19 7.04 7.807499999999999 Muy Bien ---------------------------------------------------------------------------------------------------2 Fuller Andrew Vicepresidente comercial 8.0 9.0 6.0 7.75 Muy Bien ---------------------------------------------------------------------------------------------------3 Leverling Janet Representante de Ventas 8.0 8.0 8.0 8.0 Muy Bien ---------------------------------------------------------------------------------------------------4 Peacock Margaret Representante de Ventas 8.32 8.0 8.0 8.16 Muy Bien ---------------------------------------------------------------------------------------------------5 Buchanan Steven Gerente de Ventas 10.0 8.0 10.0 9.5 Muy Bien ---------------------------------------------------------------------------------------------------6 Suyama Michael Representante de Ventas 8.0 5.0 8.0 7.25 Muy Bien ---------------------------------------------------------------------------------------------------7 King Robert Representante de Ventas 8.91 8.0 9.0 8.705 Muy Bien ---------------------------------------------------------------------------------------------------8 Callahan Laura Cordinador ventas interno 8.0 1.14 5.57 5.6775 Muy Bien ---------------------------------------------------------------------------------------------------9 Dodsworth Anne Representante de ventas 8.0 7.5 8.0 7.875 Muy Bien ----------------------------------------------------------------------------------------------------
24
=============================================================== ===================================== Informacin general del rendimiento del grupo de estudiantes =============================================================== ===================================== Promedio de Windows:8.35888888888889 Promedio de Word: 6.981111111111111 Promedio de Excel: 7.734444444444445 Promedio del Grupo: 7.8583333333333325 ---------------------------------------Maxima Calificacion: Alumno:Buchanan Steven Promedio:9.5 Minima Calificacion: Alumno:Callahan Laura Promedio:5.6775 ---------------------------------------Varianza de los promedios:0.9811380863285476
La clase ArchivoEnt hace el trabajo de leer los datos del archivo entrada.txt . La ubicacin de ese archivo es especificada por la variable String ruta en la lnea 14 y puede ser cambiada. El constructor ArchivoEnt(String nombarchent) crea el flujo al archivo de entrada y crea un objeto de la clase DataInputStream para leer los datos con formato y todo se hace en un try - catch por si hay un error de tipo IOException . El mtodo leer() de la lnea 36 a la 56 hace el trabajo de leer un registro del archivo con datos con formato y emplea los mtodos de la clase DataInputStream , readInt() , readUTF() , y readDouble() regresando un objeto de la clase Alumno , el mtodo cerrar() de la lnea 58 a la 65 cierra el flujo de entrada que abrimos con el mtodo ent.cloose() lo cual es importante para evitar un problema con el administrador de archivos del sistema operativo.
1. /** 2. * Clase publica ArchivoEnt y que es necesaria para el 3. * programa EvaluadorArchivos2.java y que ensea a 4. * utilizar las clases DataInputStream y DataOutputStream 5. * para usar datos con formato en archivos. 6. * @autor Oscar A. Gonzlez Bustamante 7. * @version 1.0 8. * Archivo: ArchivoEnt.java 9. */ 10. 11. import java.io.*; 12. 13. public class ArchivoEnt { 14. static String ruta = "C:\\j2sdk141\\ejemplos\\E-S\\"; 15. private File fichero; 16. private FileInputStream f; 17. private DataInputStream ent; 18. boolean fin; 19. 20. 21. ArchivoEnt(String nombarchent) { Profesor: Carlos A. Ruiz De La Cruz Melo
25
22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67.
try { fin = false; fichero = new File(ruta+nombarchent); f = new FileInputStream(fichero); ent = new DataInputStream( f ); } catch(IOException ioe) { System.err.println("Se ha producido un Error: " + ioe.getMessage()); ioe.printStackTrace(); } } //Retorna si nos encontramos al final del archivo public boolean eof() { return fin; } public Alumno leer() { Alumno reg= null; try{ //lee un registro de Alumno del archivo reg= new Alumno(ent.readInt(), ent.readUTF(), ent.readUTF(), ent.readUTF(), ent.readUTF(), ent.readDouble(), ent.readDouble(), ent.readDouble() ); return reg; }catch(EOFException eof) { fin=true;} catch(IOException ioe) { System.err.println("Se ha producido un Error: " + ioe.getMessage()); ioe.printStackTrace(); } return reg; } public void cerrar(){ try { ent.close(); } catch(IOException ioe) { System.err.println("Se ha producido un Error: " + ioe.getMessage()); ioe.printStackTrace(); } } } // de la clase ArchivoEnt
La clase ArchivoSal hace el trabajo de escribir los datos del archivo salida.txt . La ubicacin de ese archivo es especificada por la variable String ruta en la lnea 14 y puede ser cambiada.
26
El constructor ArchivoSal(String nombarchsal) crea el flujo al archivo de salida y crea un objeto de la clase DataOutputStream para escribir los datos con formato y todo se hace en un try - catch por si hay un error de tipo IOException . El mtodo insertar(Alumno reg) de la lnea 33 a la 48 hace el trabajo de escribir un registro de la clase Alumno con formato y emplea los mtodos de la clase DataOutputStream , writeInt() , writeUTF() , y writeDouble() , el mtodo cerrar() de la lnea 51 a la 58 cierra el flujo de salida que creamos con el mtodo sal.cloose() , adicionalmente a esto primero liberamos el flujo de salida con el mtodo sal.flush() lo cual es importante para evitar un problema con el sistema operativo.
1. /** 2. * Clase publica ArchivoSal y que es necesaria para el 3. * programa EvaluadorArchivos2.java y que ensea a 4. * utilizar las clases DataInputStream y DataOutputStream 5. * para usar datos con formato en archivos. 6. * @autor Oscar A. Gonzlez Bustamante 7. * @version 1.0 8. * Archivo: ArchivoSal.java 9. */ 10. 11. import java.io.*; 12. 13. public class ArchivoSal { 14. static String ruta = "C:\\j2sdk141\\ejemplos\\E-S\\"; 15. private File fichero; 16. private FileOutputStream f; 17. private DataOutputStream sal; 18. 19. 20. ArchivoSal(String nombarchsal) { 21. 22. try { 23. fichero = new File(ruta+nombarchsal); 24. f = new FileOutputStream(fichero); 25. sal = new DataOutputStream( f ); 26. } catch(IOException ioe) { 27. System.err.println("Se ha producido un Error: " + ioe.getMessage()); 28. ioe.printStackTrace(); 29. } 30. 31. } 32. 33. public void insertar(Alumno reg ) 34. { 35. try { 36. sal.writeInt(reg.getId()); 37. sal.writeUTF(reg.getNombre()); 38. sal.writeUTF(reg.getApellidos()); 39. sal.writeUTF(reg.getCargo()); 40. sal.writeUTF(reg.getTratamiento()); Profesor: Carlos A. Ruiz De La Cruz Melo 27
41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60.
sal.writeDouble(reg.getExamen(1)); sal.writeDouble(reg.getExamen(2)); sal.writeDouble(reg.getExamen(3)); } catch(IOException ioe) { System.err.println("Se ha producido un Error: " + ioe.getMessage()); ioe.printStackTrace(); } }
public void cerrar(){ try { sal.flush(); sal.close(); } catch(IOException ioe) { System.err.println("Se ha producido un Error: " + ioe.getMessage()); ioe.printStackTrace(); } } } // fin de la clase de ArchivoSal
La clase Persona establece los campos y mtodos accesores get y modificadores o mutadores set para obtener o cambiar los valores de las variables miembro de la clase. Esta clase heredar todos estos miembros a su subclase Alumno y que son utilizados a lo largo del programa ejemplo.
1. /** 2. * Clase publica Persona que es necesaria para el 3. * programa EvaluadorArchivos2.java y que ensea a 4. * utilizar las clases DataInputStream y DataOutputStream 5. * para usar datos con formato en archivos. 6. * @autor Oscar A. Gonzlez Bustamante 7. * @version 1.0 8. * Archivo: Persona.java 9. */ 10. 11. 12. public class Persona { 13. protected int id; 14. protected String apellidos; 15. protected String nombre; 16. protected String cargo; 17. protected String tratamiento; 18. 19. Persona() { 20. id=-1; 21. nombre=null; 22. apellidos=null; 23. tratamiento=null; 24. cargo=null; 25. } Profesor: Carlos A. Ruiz De La Cruz Melo
28
26. 27. Persona (int id, String apellidos, String nombre, String cargo, String tratamiento) { 28. this.id = id; 29. this.apellidos = apellidos; 30. this.nombre = nombre; 31. this.cargo = cargo; 32. this.tratamiento = tratamiento; 33. } 34. 35. // metodos accesores y modificadores 36. public int getId() { return id;} 37. public void setId(int nuevoid) { id = nuevoid; } 38. public String getApellidos() { return apellidos;} 39. public void setApellidos(String nuevoapellidos) { apellidos = nuevoapellidos;} 40. public String getNombre() { return nombre; } 41. public void setNombre(String nuevonombre) { nombre = nuevonombre; } 42. public String getCargo() { return cargo; } 43. public void setCargo(String nuevocargo) { cargo = nuevocargo;} 44. public String getTratamiento() { return tratamiento; } 45. public void setTratamiento(String nuevotratamiento) { tratamiento = nuevotratamiento; } 46. 47. } // fin de Persona
La clase Alumno que es hija de la clase Persona . En esta clase se manejan las calificaciones de los exmenes de cada alumno con las variables de tipo doble exa1, exa2 y exa3, la media o promedio con la variable de tipo doble promedio y la calificacin con la variable String calificacion . Tiene los mtodos getPromedio() y setPromedio() que hacen las operaciones del clculo del promedio ponderado, y los mtodos setCalificacion() y getCalificacin() para la obtencin de la calificacin en base al promedio. Implementa la interface ConstantesUtiles para manejar un arreglo de Strings para asignar la calificacin.
1. /** 2. * Clase publica Alumno y que es subclase 3. * de la clase Persona y que es necesaria para el 4. * programa EvaluadorArchivos2.java y que ensea a 5. * utilizar las clases DataInputStream y DataOutputStream 6. * para usar datos con formato en archivos. 7. * @autor Oscar A. Gonzlez Bustamante 8. * @version 1.0 9. * Archivo: Alumno.java 10. */ 11. 12. 13. public class Alumno extends Persona implements ConstantesUtiles { 14. private double exa1, exa2, exa3; 15. private double promedio; 16. private String calificacion; 17. 18. Alumno() { Profesor: Carlos A. Ruiz De La Cruz Melo 29
19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68.
super(-1,null,null,null,null); exa1=-1; exa2=-1; exa3=-1; promedio=-1; calificacion=null; } Alumno(int id, String apellidos, String nombre, String cargo, String tratamiento, double exa1, double exa2, double exa3) { super(id,apellidos,nombre,cargo,tratamiento); this.exa1 = exa1; this.exa2 = exa2; this.exa3 = exa3; } public void setExamen(double examen, int noexa) { if ( noexa == 1 ) exa1 = examen; //windows if ( noexa == 2) exa2 = examen; //word if ( noexa == 3 ) exa3 = examen; //excel } public double getExamen(int noexa) { if ( noexa == 1 ) return exa1; else if ( noexa == 2) return exa2; else if ( noexa == 3 ) return exa3; else return -1; } public void setPromedio() { promedio = exa1*0.5 + exa2*0.25 + exa3*0.25; } public double getPromedio() { setPromedio(); return promedio; } public void setCalificacion() { if ( promedio== 10.0 ) calificacion = calificativo[0] ; else if ( promedio <= 9.999 && promedio >= 9.0) calificacion = calificativo[1]; else if ( promedio <= 8.9999 && promedio >= 8.0) calificacion = calificativo[1]; else if ( promedio <= 7.999 && promedio >= 7.0) calificacion = calificativo[1]; else if ( promedio <= 6.999 && promedio >= 0.0) calificacion = calificativo[1];
30
69. else calificacion = null; 70. } 71. 72. 73. public String getCalificacion() { 74. setCalificacion(); 75. return calificacion; 76. } 77. 78. } // fin de Alumno
La interface ConstantesUtiles solo sirve para declarar un arreglo constante de objetos String para cada una de las calificaciones y se utiliza en la clase Alumno .
1. 2. 3. 4.
/** * Interface publica con constantes que necesita * el programa EvaluadorArchivos2.java y que ensea a * utilizar las clases DataInputStream y DataOutputStream
5. * para usar datos con formato en archivos. 6. * @autor Oscar A. Gonzlez Bustamante 7. * @version 1.0 8. * Archivo: ConstantesUtiles.java 9. */ 10. 11. public interface ConstantesUtiles { 12. 13. public static String calificativo[] = {
Finalmente la clase Escribe tiene el mtodo ponRaya( int lim, String simb ) el cual se emplea para escribir lneas de smbolos para separar los resultados de la salida y su uso es utilitario.
1. 2. 3. 4.
/** * Clase publica Escribe y que es necesaria para el * programa EvaluadorArchivos2.java y que ensea a * utilizar las clases DataInputStream y DataOutputStream
5. * para usar datos con formato en archivos. 6. * @autor Oscar A. Gonzlez Bustamante 7. * @version 1.0 Profesor: Archivo: Escribe.java De La Cruz Melo 8. * Carlos A. Ruiz 9. */ 10. class Escribe { 11. public static void ponRaya(int lim, String simb) { 12. for (int i = 1; i <= lim; i++)
31
Tanto la interface ConstantesUtiles y la clase Escribe pudieron haber estado en un paquete y luego importadas, incluso las clases Alumno , Persona , ArchiEnt y ArchiSal deberan haber estado en un paquete de clases y luego importadas en la clase EvaluadorArchivos2 pero esto se deja como ejercicio al lector.
32
salArch.println(nomb); salArch.close(); } catch(java.io.IOException ioex){ } } public void mostrar(){ try { FileReader fr=new FileReader("text.txt"); BufferedReader entrada=new BufferedReader(fr); String s; while((s=entrada.readLine( ) )!=null){ System.out.println("Salida del archivo : "+s); entrada.close(); } catch(java.io.FileNotFoundException fnfex){ } catch(java.io.IOException ioex){ } }
public static void main(String arg[ ]){ TEXTO fun= new TEXTO(); fun.escritura(fun.dato("Ingrese algo al archivo > ")); fun.mostrar(); } }
33
} public void mostrar(){ // PERMITE MOSTRAR EL VALOR REAL EN EL ARCHIVO String s; try { DataInputStream disco= new DataInputStream(new BufferedInputStream(new FileInputStream("prueba.dat"))); File f= new File("prueba.dat"); double d2; while(f.exists( ) ){ d2=disco.readDouble( ); System.out.println(d2); } disco.close( ); } catch(java.io.FileNotFoundException fnfex){ } catch(java.io.IOException ioex){ } } public static void main(String arg[ ]){ BINARIO fun= new BINARIO( ); fun.escritura(Float.parseFloat(fun.dato("Ingrese un real > "))); fun.escritura(Float.parseFloat(fun.dato("Ingrese un real > "))); fun.mostrar(); } }
34
String s; int i; public MiClase(String s, int i) { this.s = s; this.i = i; } public String toString() { return "s=" + s + "; i=" + i; } }
35
} } class ALUMNO implements Serializable { String c; String n; public ALUMNO(String c,String n){ public String Rn( ){ return n; } public String Rc( ){ return c; } }
this.c=c; this.n=n;
Ejemplo 5. Programa que realiza varias operaciones sobre un archivo (ingresar datos, eliminar segn el cdigo o clave, modificar datos segn la clave, ordenar por clave y mostrar todos los datos del archivo )
A continuacin un ejemplo de los datos que se puede ingresar al archivo CLAVE 10 20 30 33 Diagrama de clases NOMBRE carlos Maria Juan Elena EDAD 35 20 40 60
PERSONA String n; Int Clave; Int edad; String leer(String m); void E( ); boolean M( ); void O( ); void B( ); void L( );
1. import java.lang.*; 2. import java.io.*; 3. class ARCH { 4. BufferedReader teclado = new BufferedReader(new 5. InputStreamReader(System.in)); 6. String n; 7. int clave=0; Profesor: Carlos A. Ruiz De La Cruz Melo 36
8. int edad=0; 9. long tregistro=58; 10. long cregistros=0; 11. public String leer(String m){ 12. System.out.print(m+" : "); 13. try{ n=teclado.readLine( ); } 14. catch(Exception e){ } 15. return n; 16. } 17. void E( ){ 18. String nombre=""; 19. try { 20. File arch=new File("archivo1.dat"); 21. RandomAccessFile archivo=new RandomAccessFile(arch,"rw"); 22. clave = Integer.parseInt(leer("dame clave")); 23. nombre=leer("dame nombre"); 24. if (nombre.length( ) < 25){ 25. for(int i=nombre.length( ); i <25; i++) nombre=nombre+" "; 26. } 27. else{ nombre=nombre.substring(0,25); }; 28. edad = Integer.parseInt(leer("dame edad")); 29. if (archivo.length( )!= 0){ 30. archivo.seek( archivo.length( ) ); 31. }; 32. archivo.writeInt(clave); 33. archivo.writeChars(nombre); 34. archivo.writeInt(edad); 35. archivo.close( ); 36. } 37. catch(FileNotFoundException f) { System.out.println("Arch. No existe"); } 38. catch (IOException e) { System.out.println("Error al escribir"); } 39. } 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. boolean M( ){ String nombre=""; try{ File arch=new File("archivo1.dat"); RandomAccessFile archivo=new RandomAccessFile(arch,"rw"); cregistros=archivo.length( )/ tregistro; int n=0; int c = Integer.parseInt(leer("dame clave a buscar")); while(n<cregistros){ archivo.seek(n*58); clave=archivo.readInt(); if(clave == c){ nombre=leer("dame nombre"); if (nombre.length() < 25){ for(int i=nombre.length(); i <25; i++) nombre=nombre+" "; } else{ nombre=nombre.substring(0,25); }; 37
57. edad = Integer.parseInt(leer("dame edad")); 58. archivo.seek(n*58); 59. archivo.writeInt(clave); 60. archivo.writeChars(nombre); 61. archivo.writeInt(edad); 62. archivo.close(); 63. return true; 64. } 65. n=n+1; 66. } 67. archivo.close(); 68. } 69. catch(FileNotFoundException f) { System.out.println("Arch. no existe"); } 70. catch (IOException e) { System.out.println("Error al escribir"); } 71. return false; 72. } 73. void O( ){ 74. int c1; 75. String n1; 76. int e1; 77. int c2; 78. String n2; 79. int e2; 80. boolean salir; 81. try { 82. File arch=new File("archivo1.dat"); 83. RandomAccessFile archivo=new RandomAccessFile(arch,"rw"); 84. cregistros=archivo.length( ) / tregistro; 85. do{ 86. salir=false; 87. for (int r=0; r < (cregistros-1); r++){ 88. archivo.seek(r*58); 89. c1=archivo.readInt( ); 90. archivo.seek((r+1)*58); 91. c2=archivo.readInt( ); 92. if(c1<c2){ 93. c1=0; 94. n1=""; 95. e1=0; 96. c2=0; 97. n2=""; 98. e2=0; 99. archivo.seek(r*58); 100. c1=archivo.readInt(); 101. for(int i = 0; i < 25; ++i){ n1 += archivo.readChar( ); }; 102. e1=archivo.readInt(); 103. archivo.seek((r+1)*58); 104. c2=archivo.readInt(); 105. for(int i = 0; i < 25; ++i){ n2 += archivo.readChar( ); }; Profesor: Carlos A. Ruiz De La Cruz Melo 38
106. e2=archivo.readInt(); 107. archivo.seek(r*58); 108. archivo.writeInt(c2); 109. archivo.writeChars(n2); 110. archivo.writeInt(e2); 111. archivo.seek((r+1)*58); 112. archivo.writeInt(c1); 113. archivo.writeChars(n1); 114. archivo.writeInt(e1); 115. salir=true; 116. } 117. } 118. }while(salir); 119. archivo.close(); 120. } 121. catch(FileNotFoundException f) { System.out.println("Arch. no existe"); } 122. catch (IOException e) { System.out.println("Error al escribir"); } 123. } 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. void B( ){ int c1; String n1=""; int e1; String nombre=""; boolean cond=false; int k; try{ File arch=new File("archivo1.dat"); RandomAccessFile archivo=new RandomAccessFile(arch,"rw"); cregistros=archivo.length( ) / tregistro; int n=0; int c = Integer.parseInt(leer("dame clave a buscar")); while(n<cregistros){ archivo.seek(n*58); clave=archivo.readInt( ); if(clave == c){ cond=true; break;} n=n+1; } k=n; if(cond){ for(;;){ k++; if(k< cregistros){ archivo.seek(k*58); c1=archivo.readInt( ); for(int i = 0; i < 25; ++i){ n1 += archivo.readChar( );}; e1=archivo.readInt( ); archivo.seek(n*58); archivo.writeInt(c1); archivo.writeChars(n1); 39
154. archivo.writeInt(e1); 155. n1=""; 156. n++; 157. } 158. else { archivo.close( ); 159. File arch2=new File("archivo1.dat"); 160. RandomAccessFile archivo2=new RandomAccessFile(arch,"rw"); 161. archivo2.setLength(n*58); 162. archivo2.close(); 163. break; 164. } 165. } 166. } 167. else archivo.close( ); 168. } 169. catch(FileNotFoundException f) { System.out.println("Arch. no existe"); } 170. catch (IOException e) { System.out.println("Error al escribir"); } 171. } 172. void L( ){ 173. int clave=0; 174. String nombre=""; 175. int edad=0; 176. try { 177. File arch=new File("archivo1.dat"); 178. RandomAccessFile archivo=new RandomAccessFile(arch,"rw"); 179. cregistros=archivo.length( ) / tregistro; 180. for (int r=0; r < cregistros; r++){ 181. clave=archivo.readInt( ); 182. for(int i = 0; i < 25; ++i){ nombre += archivo.readChar( ); }; 183. edad=archivo.readInt( ); 184. System.out.println(clave+" "+nombre+" "+edad); 185. nombre=""; 186. }; 187. archivo.close( ); 188. } 189. catch(FileNotFoundException f) { System.out.println("Arch. no existe"); } 190. catch (IOException e) { System.out.println("Error al escribir"); } 191. } 192. 193. 194. 195. 196. 197. 198. public static void main(String[ ] args) { ARCH a=new ARCH(); for(;;){ System.out.println("Ingresar <1>\n Ver <2> \n Ordenar <3> \n Modificar <4> \n Borrar <5> \n Salir <6>"); switch (Integer.parseInt(a.leer("opcion : "))){ case 1:a.E( );break; 40
case 2:a.L( );break; case 3:a.O( );break; case 4:a.M( );break; case 5:a.B( );break; case 6:System.exit(0); } } } // cierra main } // cierra clase
Ejercicio Escriba un programa usando archivos que permita guardar la informacin de una factura con datos como fecha, nombre de la empresa y lista de tems (cdigo, precio unitario, descripcin del producto, cantidad)
5. ANALISIS DE RESULTADOS Es un concepto importante, pues permite que un objeto pueda ser usado en diferentes momentos a lo largo del tiempo, por el mismo programa o por otros, as como en diferentes instalaciones de hardware en el mismo momento. Un objeto persistente es aqul que conserva su estado en un medio de almacenamiento permanente, pudiendo ser reconstruido por el mismo u otro proceso. Al objeto no persistente lo llamamos efmero. Los datos generalmente se almacenan con algn tipo de organizacin, por ejemplo, un registro, que agrupa datos de diferentes tipos (enteros, string, etc). En los lenguajes de programacin OO, como Java, C++, etc, los datos se organizan en un tipo de datos definido por el usuario (TAD) que recibe el nombre de Clase. Esto presenta la ventaja de que adems de incluir los campos tradicionales de un registro (en forma de atributos) tambin puede incorporar una serie de mtodos que permiten procesar de manera mas fcil los campos o atributos de la clase.
3 en 21 Das. Prentice Hall Hispanoamericana S. A. 1998 Bertrand Meyer. Construccin de Software Orientado a Objetos. Prentice Hall, segunda edicin Andrew C. Staugaard, Jr. Tcnicas Estructuradas y Orientadas a Objetos. Prentice Hall Hispanoamericana S.A. 1998. Fco. Javier Ceballos. Java 2 Curso de Programacin. Alfaomega Ra-Ma Luis Joyanes Aguilar. Programacin Orientada a Objetos, Segunda edicin. McGraw-Hill Interamericana De Espaa S.A. U, 1998 Herbert Schildt. Turbo C/C++ Manual de Referencia, una informacin completa ideal para todo usuario de Turbo C/C++. Osborne/ McGraw-Hill, 1999
41