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