Operaciones con ficheros
Ejercicio resuelto
Crear un programa que sea capaz de contar cuántas vocales hay en un fichero.
El programa padre debe lanzar cinco procesos hijo, donde cada uno de ellos se ocupará de contar una vocal concreta (que puede ser minúscula o mayúscula). Cada subproceso que cuenta vocales deberá dejar el resultado en un fichero. El programa padre se ocupará de recuperar los resultados de los ficheros, sumar todos los subtotales y mostrar el resultado final en pantalla.
Operaciones con ficheros
Tanto en este ejercicio como en muchos otros vamos a necesitar realizar ciertas operaciones con ficheros. Para aumentar nuestra productividad utilizaremos una clase llamada UtilidadesFicheros
que nos permita realizar ciertas tareas como las siguientes:
import java.io.*; import java.util.ArrayList; public class UtilidadesFicheros {
- Obtener un objeto
BufferedReader
a partir de un nombre de fichero de tipoString
. Llamaremos a este métodogetBufferedReader
y lo utilizaremos para poder manejar un fichero mediante una clase de muy alto nivel que nos facilita la lectura de ficheros. En el listado adjunto se puede consultar dicho método.
public static BufferedReader getBufferedReader(String nombreFichero) throws FileNotFoundException {
FileReader lector;
lector = new FileReader(nombreFichero);
BufferedReader bufferedReader;
bufferedReader = new BufferedReader(lector);
return bufferedReader;
}
- De la misma forma crearemos un método
getPrintWriter
que nos devuelva un objeto de la clasePrintWriter
para poder realizar fácilmente operaciones de escritura en ficheros. En el listado adjunto se muestra el código.
public static PrintWriter getPrintWriter(String nombreFichero) throws IOException {
PrintWriter printWriter;
FileWriter fileWriter;
fileWriter = new FileWriter(nombreFichero);
printWriter = new PrintWriter(fileWriter);
return printWriter;
}
- Aunque nos estamos anticipando, puede ser útil tener un método que dado un nombre de fichero nos devuelva un
ArrayList<String>
con todas las líneas que hay en el fichero. En este ejercicio no lo usaremos. Este método podría implementarse así:
public static ArrayList<String> getLineasFichero(String nombreFichero) throws IOException {
ArrayList<String> lineas = new ArrayList<String>();
BufferedReader bfr = getBufferedReader(nombreFichero);
//Leemos líneas del fichero...
String linea = bfr.readLine();
while (linea != null) {
//Y las añadimos al array
lineas.add(linea);
linea = bfr.readLine();
}
//Fin del bucle que lee líneas
return lineas;
}
} //fin de la clase UtilidadesFicheros
Procesado de ficheros
Necesitaremos una clase ProcesadorFichero
que nos permita procesar los ficheros de la forma pedida. Antes de crear un programa multiproceso empezaremos por crear una clase simple que nos resuelva este problema.
Dicha clase tendrá un método hacerRecuento
que resuelva el problema de contar el número de apariciones en un fichero dejando el total de apariciones en un fichero de salida distintos. En el código adjunto podemos ver como podría implementarse dicho método.
// Dado un fichero de entrada y una letra
// contamos cuantas veces aparece dicha letra
// y dejamos el recuento en un fichero de salida
import java.io.*;
public class ProcesadorFichero {
public static void hacerRecuento(String fichEntrada, String letra,String fichSalida) throws FileNotFoundException,IOException {
BufferedReader br;
br = UtilidadesFicheros.getBufferedReader(fichEntrada);
PrintWriter pw;
pw = UtilidadesFicheros.getPrintWriter(fichSalida);
String lineaLeida;
lineaLeida = br.readLine();
int totalVocales = 0;
//Mientras no queden líneas....
while (lineaLeida != null) {
//...recorremos la linea...
for (int i = 0; i < lineaLeida.length(); i++) {
char letraLeida = lineaLeida.charAt(i);
char letraPasada = letra.charAt(0);
// incrementamos el contador
if (letraLeida == letraPasada) {
totalVocales++;
}
}
// Pasamos a la siguiente linea
lineaLeida = br.readLine();
}
//Escribimos el total de vocales
//en el fichero de salida
pw.println(totalVocales);
pw.flush();
//Y cerramos los ficheros
pw.close();
br.close();
}
La clase ProcesadorFichero
será lanzada desde otra clase que llamaremos Lanzador
. Nuestra ProcesadorFichero
recogerá en su método main
los siguientes parámetros:
- El nombre del fichero a procesar. Lo llamaremos
nombreFicheroEntrada
y estará en la posición 0 de los argumentos. - La letra de la que hay que hacer el recuento de apariciones. La llamaremos
letra
y estará en la posición 1. - El nombre del fichero donde se dejarán los resultados. Lo llamaremos
nombreFicheroResultado
y estará en la posición 1 de los argumentos.
El código del main se muestra a continuación.
/**
* Dado un fichero pasado como argumento, contará cuantas
* apariciones hay de una cierta vocal (pasada como argumento)
* y dejará la cantidad en otro fichero (también pasado como
* argumento)
* @throws IOException
* @throws FileNotFoundException
*/
public static void main(String[] args) throws FileNotFoundException, IOException {
String nombreFicheroEntrada = args[0];
String letra = args[1];
String nombreFicheroResultado = args[2];
hacerRecuento(nombreFicheroEntrada, letra, nombreFicheroResultado);
}
} //fin de la clase ProcesadorFichero
Lanzamiento de los procesos
La clase Lanzador
tendrá un método main
que se encargará de varias cosas:
- Recoger el primer parámetro (
args[0]
), que contendrá el fichero a procesar. - Una vez recogidos los parámetros, se lanzarán los procesos utilizando la clase
ProcessBuilder
. - Los procesos se ejecutarán y después recogeremos los resultados de los ficheros.
En el código siguiente puede verse el método main
de esta clase Lanzador
. La recogida de resultados se deja como ejercicio:
public class LanzadorProcesadorFichero { public static void main(String[] args) throws IOException, InterruptedException { String ficheroEntrada; ficheroEntrada = args[0]; String[] vocales = {"a", "e", "i", "o", "u"}; } }
¿Recogida de resultados?
Mejora: Esperar a que terminen todos los procesos en lugar de un tiempo al azar.
Mejora: contar las mayúsculas, las minúsculas y los acentos.
Deja una respuesta
Lo siento, debes estar conectado para publicar un comentario.