Download Programación Java Introducción a Archivos de datos de Entrada
Document related concepts
no text concepts found
Transcript
Programación Java Introducción a Archivos de datos de Entrada Consideremos el siguiente algoritmo: Algoritmo (no modular) para determinar y mostrar el promedio aritmético (media aritmética) de los elementos de cualquier conjunto finito no vacío de números reales. ENTRADA: PROPÓSITO: SALIDA: Un conjunto finito cualquiera no vacío de números reales. Determinar el promedio aritmético de los elementos en el conjunto. El promedio aritmético de los elementos en el conjunto. Pasos: 1. Iniciliazar Contador y acumulador aditivo Suma. 1.1 Contador ← 0 1.2 Suma ← 0 2. Mientras haya números en el conjunto. 2.1 Considerar el Próximo de los números 2.2 Contador ← Contador + 1 2.3 Suma ← Suma + Próximo 3. Calcular Promedio Aritmético. 3.1 Promedio Aritmético ← Suma/Contador 4. Mostrar resultados. 4.1 Promedio Aritmético Cuando son muchos los datos de entrada es conveniente almacenarlos en un archivo para luego procesarlos mediante programación. Para manejar un archivo existente de datos, en general, hay que llevar a cabo los siguientes tres pasos: 1. Abrir el archivo. Cuando se abre un archivo se establece una conexión entre el archivo y el programa de computadoras. 2. Leer información del archivo o escribir información en el archivo. ● Cuando se lee información de un archivo, el archivo se clasifica como un archivo de entrada. ● Cuando se escribe información en un archivo, el archivo se clasifica como un archivo de salida. 3. Cerrar el archivo cuando el programa termine de manejar el archivo. 1 En general, hay dos tipos de archivos: de texto y binarios. Un archivo de texto contiene datos que han sido codificados como texto. Aunque el archivo contenga números, estos números se almacenan como texto en el archivo como una serie de caracteres. Como resultado, el archivo se puede abrir y ver su contenido en un editor de texto como Notepad. Un archivo binario contiene datos que no se han convertido a texto. Como consecuencia, no se puede ver el contenido de un archivo binario con un editor de texto. De momento, trabajaremos solamente con archivos de texto. Java provee clases estándares o predefinidas para trabajar con archivos. En general, para trabajar con estas clases predefinidas se deben incluir la siguientes oraciónes import: import java.io.*; import java.util.*; En particular, para leer datos de un archivo se pueden utilizar las clases predefinidas Scanner y File. La clase Scanner discutida anteriormente también se puede utilizar para leer datos de un archivo. En vez de usar System.in,que representa el teclado, como argumento se usa una referencia a un objeto de la clase File. Ejemplo: ... import java.io.*; import java.util.Scanner; ... File miArchivo = new File("Datos.txt"); Scanner lectorDeArchivos = new Scanner(miArchivo); La instrucción File miArchivo = new File("Datos.txt"); crea una instancia de la clase File. La clase File está en el paquete java.io.* y se usa para representar un archivo. En esa instrucción se está usando la cadena de caracteres "Datos.txt" como argumento. Esto crea un objeto tipo File que representa (referencia) el archivo Datos.txt. En este caso diremos que Datos.txt es el nombre físico del archivo y miArchivo es su nombre lógico. Por lo tanto, se establece una asociación entre el nombre físico del archivo y su nombre lógico. En la instrucción Scanner lectorDeArchivos = new Scanner(miArchivo); se incluye una referencia al objeto miArchivo como argumento. Esto crea un objeto de la clase Scanner que usa el archivo Datos.txt como su fuente de entrada. 2 Cuando la aplicación haya terminado de leer datos del archivo, se usa el método close de la clase Scanner para cerrar el archivo. Por ejemplo, si la variable lectorDeArchivos referencia o representa un objeto de la clase Scanner, entonces la instrucción lectorDeArchivos.close(); cierra el archivo que es la fuente de entrada del objeto. Incluyendo una cláusula throws en el encabezamiento de un método Cuando ocurre un evento inesperado durante la corrida de un programa en Java, se dice que el programa produjo una excepción. Por ejemplo, si se trata de leer más datos que los que contiene un archivo, entonces el programa no puede continuar hasta que la situación se corrija o resuelva. Por lo tanto, se produce una excepción y el programa detiene su ejecución. Podemos suponer que una excepción es una señal que indica que el programa no puede continuar su ejecución normal hasta que se resuelva el evento inesperado. Cuando se produce una excepción, el programa suspende su ejecución o corrida normal. Si un método es capaz de producir una excepción, entonces el método debe tratar de trabajar con la excepción o producirla (tirarla). Para que el método pueda trabajar con la excepción, el programador debe incluir líneas correspondientes de código para indicarle al método posibles cursos de acción a seguir cuando una situación inesperada ocurra; de lo contrario se le debe permitir al método que produzca una excepción cuando ocurra un evento inesperado. Para permitirle a un método que produzca una excepción cuando se presente un evento inesperado para el cual no se ha trabajado alternativa alguna, se escribe una cláusula throws en el encabezamiento del método. La cláusula throws tiene que indicar el tipo de excepción que se debe producir. Por ejemplo, public static void main(String[] args) throws IOException Este encabezamiento indica que el método main es capaz de producir una excepción del tipo IOException. Si el método main no efectúa una operación con archivos, pero invoca un método que sí lo hace, entonces tanto el método main como el método que efectúa una operación con archivos deben contener la cláusula throws IOException como parte del encabezamiento. De otra forma, se producirá un error de compilación. 3 Leyendo valores de tipos primitivos de un archivo Se indicó anteriormente que para leer datos de un archivo se pueden utilizar las clases predefinidas Scanner y File. La clase Scanner, que además de usarse para leer datos entrados por el teclado, también se puede utilizar para leer datos de un archivo. En vez de usar System.in, que representa el teclado como argumento, se usa como argumento una referencia a un objeto de la clase File. Consideremos nuevamente las siguientes líneas de código: ... import java.io.*; import java.util.Scanner; ... File miArchivo = new File("Datos.txt"); Scanner lectorDeArchivos = new Scanner(miArchivo); Recuerde que cuando discutimos el tema El Sistema Estándar de Entrada de Información en Java vimos que la clase Scanner provee métodos para leer valores primitivos. Estos métodos se llaman nextByte, nextDouble, nextFloat, nextInt, nextLong y nextShort. Esta clase también contiene métodos para leer valores de un archivo. Veamos los pasos que hay que seguir cuando se escribe un programa que lee datos de un archivo: 1. Necesitamos incluir la instrucción import java.util.Scanner; en la sección superior del programa para poder utilizar la clase Scanner. 2. También necesitamos incluir la instrucción import java.io.*; en la parte superior del programa para poder utilizar la clase File. 3. Como no hemos discutido cómo trabajar cuando se produce una excepción, cualquier método que use un objeto de la clase Scanner para abrir un archivo debe contener como parte de su encabezamiento la cláusula throws IOException. 4. Se debe crear un objeto tipo File y se usa como argumento el nombre físico del archivo como una cadena de caracteres. Por ejemplo: File miArchivo = new File("Datos.txt"); 4 5. Se crea un objeto tipo Scanner y se usa como argumento una referencia al objeto tipo File. Por ejemplo: Scanner lectorDeArchivos = new Scanner(miArchivo); 6. Para leer valores primitivos se usan métodos tales como nextInt, nextDouble, y así por el estilo. 7. Cuando se termine de leer valores de un archivo se utiliza el método close de la clase Scanner para cerrar el archivo. Por ejemplo, si la variable miArchivo es una referencia a un objeto de la clase Scanner, entonces la siguiente instrucción cierra el archivo que es la fuente de entrada del objeto: miArchivo.close(); Detectando el final del archivo Es usual que un programa lea el contenido de un archivo sin saber el número de valores que se han guardado en el archivo. Constituye un error lógico el que un programa trate de leer más valores que los que un archivo contiene. La clase Scanner contiene el método hasNext que se puede utilizar para determinar si el archivo contiene más datos por leer. El método hasNext se invoca antes que cualquier otro método para leer datos de un archivo. Si hay más datos por leer, entonces el método hasNext devuelve true. Si se llega al final del archivo y no hay más datos por leer, el método hasNext devuelve false. Por ejemplo, ... File miArchivo = new File("Datos.txt"); Scanner lectorDeArchivos = new Scanner(miArchivo); ... while (lectorDeArchivos.hasNext()){ .... } 5 Posible codificación del algoritmo no modular anterior /* Programa Ejemplo: Este programa lee números reales de un archivo de entrada, calcula y muestra su promedio aritmético. Archivo: PromedioAritmetico.java Archivo de Datos de Entrada: Numeros.txt */ import java.util.Scanner;//Necesario para la clase Scanner import java.io.*;//Necesario para leer de un archivo y para IOException public class PromedioAritmetico{ public static void main(String[] args) throws IOException { double suma = 0.0;//Se inicializa el acumulador a 0.0. double contador = 0.0;//Se inicializa el acumulador a 0.0. //Se abre el archivo. File archivoDatos = new File("Numeros.txt"); Scanner lectorDeArchivos = new Scanner(archivoDatos); /*Se leen todos los valores del archivo y se calcula su suma.*/ while (lectorDeArchivos.hasNext()){ //Se lee un valor del archivo. double numero = lectorDeArchivos.nextDouble(); //Se añade el número a suma y se incrementa contador en 1. suma = suma + numero; contador = contador + 1; } //Se calcula el promedio aritmético double promedioAritmetico = suma/contador; lectorDeArchivos.close();//Se cierra el archivo. //Muestra la suma de los resultados. System.out.println("El promedio aritmetico de los numeros en el archivo"+" Numeros.txt es " + promedioAritmetico); }//Termina el método main. }//Termina la clase PromedioAritmetico. 6 Algoritmo modular para determinar y mostrar el promedio aritmético (media aritmética) de los elementos de cualquier conjunto finito no vacío de números reales. ENTRADA: PROPÓSITO: SALIDA: Un conjunto finito cualquiera no vacío de números reales. Determinar el promedio aritmético de los elementos en el conjunto. El promedio aritmético de los elementos en el conjunto. import java.util.Scanner; import java.io.*;/ clase PromedioAritmeticoModular{ método void main(String[] args) throws IOException { mensajeInicial(); double promedioAritmetico ← calculaPromedioAritmetico(); salida(promedioAritmetico); }//termina método main métod void mensajeInicial(){ System.out.println("Este programa lee números reales de un archivo de entrada, calcula y muestra su promedio aritmético."); }//termina método mensajeInicial; método double calculaPromedioAritmetico() throws IOException { double suma0 ← 0; int contador ← 0; File archivoDatos ← new File("Numeros.txt"); Scanner lectorDeArchivos ← new Scanner(archivoDatos); mietras (lectorDeArchivos.hasNext()){ double numero ← lectorDeArchivos.nextDouble(); suma ← suma + numero; contador ← contador + 1; } lectorDeArchivos.close();//se cierra el archivo //Se procede a calcular el promedio aritmético double promedioAritmetico ← suma/contador; return promedioAritmetico; }//termina método calculaPromedioAritmetico método void salida(double promedioAritmetico){ System.out.println("El promedio aritmetico de los numeros en el archivo"+" Numeros.txt es " + promedioAritmetico); }//termina método salida }//termina clase PromedioAritmeticoModular 7 Ejercicio: Codifique el algoritmo modular anterior. Luego, compile y corra la aplicación modular correspondiente. 8