Crear el Constructor
Queremos leer un fichero en nuestra aplicación, pero primero queremos chequear si puede leerse. Asumiendo que hemos asociado el nombre del fichero con un objeto File llamado f, ¿cómo chequeamos si se puede leer el fichero?
Chequeamos si un fichero específico es leíble llamando al método canRead de la clase File. Como el fichero está asociado con un objeto File a través de un identificador de referencia f, el siguiente código es correcto:
if (f.canRead()) {
System.out.println("File can be read.");
}
La clase File tiene muchos métodos útiles para chequear el estado o para crear directorios y ficheros. Aprenderemos más sobre la clase File más adelante. Ahora, empezemos el constructor de la clase NorthPanel.
Crear el Constructor
La clase NorthPanel es la plantilla para el objeto que rellena la parte superior del panel Dive Logs, por eso le adjuntamos un constructor. Este panel construye un área de texto y lee un fichero, mostrando el texto en el área de texto. El constructor construye los componentes GUI, como un área de texto con un borde, y llama a un método especial que defineremos más adelante para leer texto desde un fichero, mostrando el texto en el área designada.
Hasta ahora, en la clase NorthPanel, tenemos el siguiente código:
package divelog;
import java.awt.*;
import javax.swing.*;
public class NorthPanel extends JPanel { // Opens class
} // Closes class
Vamos añadir una sentencia import, declarar variables y crear un área de texto.
| Sigue estos pasos... |
- Abre el fichero NorthPanel.java en tu editor de texto.
- Añade la sentencia import en negrita de abajo:
import java.awt.*;
import javax.swing.*;
import java.io.*;
- Añade las siguientes variables, después de la declaración de la clase:
public class NorthPanel extends JPanel { //opens class
JTextArea instruct;
String str;
//BufferedReader is explained later
BufferedReader br;
- Añade el siguiente constructor:
public NorthPanel() { //opens constructor
setBackground(Color.white);
instruct = new JTextArea(5,60);
instruct.setLayout(new FlowLayout(FlowLayout.CENTER));
instruct.setBorder(BorderFactory.createTitledBorder(Detailing Dives "));
instruct.setLineWrap(true);
instruct.setWrapStyleWord(true);
instruct.setEditable(false);
// Method that is defined later
readFileIntoTextArea();
add(instruct);
} //closes constructor
|
Este constructor:
- Selecciona a blanco el color de fondo de este panel.
- Inicializa un objeto JTextArea con 5 filas y 60 columnas.
- Selecciona la distribución del área de texto con un controlador FlowLayout inicializando dicha clase.
- Llama al método setBorder y lo pasa en una llamada al método BorderFactory y al método estático creatTitledBorder para crear un borde con el texto "Detailing Dives".
- Se asegura de que el texto insertado en el área de texto rompe las líneas poniendo los métodos setLineWrap y setWrapStyleWord a true.
- Hace que el área de texto sea de sólo lectura llamando al método setEditable con false.
- Llama a readFileIntoTextArea, un método que definiremos más adeltante.
- Añade el objeto textArea que acabamos de crear al flowLayout de este panel.
El objeto NorthPanel contiene un objeto textArea, pero el constructor llama a un método que todavía no se ha definido. El método readFileIntoTextArea hace lo que su nombre sugiere: lee un fichero y pone su contenido en un área de texto. Aquí es donde tiene lugar la Java I/O. Cuando se llama al constructor, crea el área de texto, luego llama al método que lee el contenido de un fichero y muestra el texto en el área de texto.
Para que podamos entender los pasos del manejo de excepciones y las distintas formas de tratar los problemas, intencionadamente no vamos a crear el fichero a leer en el área de texto hasta más adelante. Por ahora, vamos a escribir código con la intención de crear una condición que nos fuerce a manejar el problema de tres formas diferentes:
- Imprimir un mensaje de error en la consola.
- Crear una caja de diálogo desplegable que alerte al usuario del problema.
- Llamar a un método que cree un fichero en el caso de que éste no exista.
Aunque antes de hacer esto, debemos entender un poco más los streams.
La clase Reader
La mayoría de los streams de datos fluyen en una sóla dirección, como sus contrapartidas en el mundo real, los rios. Un stream de datos es o un stream de entrada o un stream de salida, y frecuentemente abrimos dos streams a la vez: uno para lectura y chequeo de validación (entrada) y otro para escritura (salida).
El diagrama de abajo muestra el árbol de clases que usaremos para leer texto desde un fichero. Reader es una clase abstracta para leer streams de caracteres. Como podemos recordar, las clases abstractas requieren que implementemos, o definamos en detalle, sus métodos. En este caso, los únicos métodos que una subclase debe implementar son read(char[], int, int) y close(). Estos son métodos últiles si queremos que nuestra aplicación lea el fichero. El problema con el método read(char[], int, int) es que sólo lee un carácter cada vez. Para leer el contenido de un fichero, necesitamos algo más práctico.
Recuerda, una clase hija tiene más funcionalidad que su clase padre porque lo hereda todo de su padre y define características adicionales que podríamos usar. Por eso, bajando por el árbol podemos encontrar InputStreamReader y BufferedReader.
Cuando construimos un InputStreamReader, las reglas de conversión también se definen para cambiar entre 16-bit Unicode y otras representaciones específicas de la plataforma. Esto es útil cuando se leen o escriben ficheros. Cada llamada a uno de los métodos InputStreamReader.read podría hacer que se leyeran uno o más bytes desde el stream de bytes subyacente. Para permitir una conversión eficiente de los bytes a caracteres, se podrían leer más bytes de los necesarios para satisfacer la operación de lectura actual. De nuevo, sólo se lee un caracter cada vez.
FileReader es una clase de conveniencia para leer ficheros de caracteres. El constructor de esta clase asume que la codificación de caracteres por defecto y el tamaño del buffer de bytes por defecto son apropiados. Es una clase útil, pero no proporciona métodos adicionales. Al usar esta clase, descendemos de InputStreamReader, lo que es bueno, pero todavía necesitamos mejores funcionalidades de lectura.
Observa la clase BufferedReader de la imagen de arriba. Esta clase lee texto desde un stream de entrada de caracteres, almacenando los caracteres proporciona una forma eficiente de lectura de caracteres, arrays y líneas. Podría especificarse el tamaño del buffer o podría utilizarse el tamaño por defecto. El tamaño por defecto es suficiente para la mayoría de los propósitos. En otras palabras, un BufferedReader mejora el rendimiento de un objeto Reader asociado proporcionando un buffer de almacenamiento temporal. Reduciendo el número de veces que se debe acceder al disco o a la red.
Ahora nuestra aplicación puede obtener alguna funcionalidad de lectura realmente buena. Esta clase incluso tiene un método readLine para leer una línea de texto a la vez. Sin embargo, BufferedReader no puede usarse por sí mismo. En su lugar, debemos envolver o encadenar un Reader dentro de un
BufferedReader. Esto se hace pasando un objeto Reader al constructor de BufferedReader.
Por ejemplo:
BufferedReader in = new BufferedReader(new FileReader("TextFile.txt"));
Si creamos o copiamos este fichero de texto llamado
example.txt, y ejecutamos la aplicación
ReadMyFile:
- Creamos un objeto String para contener todo el texto a leer.
- Encerramos el código en sentencias try y catch para manejo de excepciones.
- Envolvemos un objeto FileReader dentro de un objeto BufferedReader.
- Usamos un bucle while y el método readLine para iterar sobre el texto e imprimirlo en la consola.
- Cerramos el stream cuando no haya más líneas de texto para leer.
Leer el Fichero dentro del TextArea
Para leer desde un fichero, conectamos con un stream de entrada y leemos desde él, usando una variable para contener el texto. Para hacer algo con el texto, vamos al método readFileIntoTextArea de la clase NorthPanel.
| Sigue estos pasos... |
- Abre el fichero NorthPanel.java en tu editor de texto.
- Después del corchete de cierre del constructor, añade la siguiente declaración de método:
{ // Closes constructor
private void readFileIntoTextArea() { // opens method
- Empieza una sentencia try con un corchete abierto y una asociación del fichero que queremos leer con un objeto File:
try { //opens try
File f = new File("divedetails.txt");
- Envuelve un ejemplar del objeto FileReader en un ejemplar de un objeto BufferedReader:
br = new BufferedReader (new FileReader(f));
- Itera sobre cada línea usando una construcción while con el método readLine, y asignalo a la variable str que creamos anteriormente:
while ((str = br.readLine()) != null) {//opens while
- Pasa el texto del fichero al área de texto con el método append de la clase JTextArea. Recuerda que creamos esta variable antes, instruct:
instruct.append(str);
- Cierra el bucle while:
} //closes while
- cierra la sentencia try:
} // close try
Aquí hay un ejemplo de cómo debería estar tu clases hasta ahora.
|
Recuerda que toda sentencia try necesita un bloque catch, y hasta ahora hemos escrito código para leer un fichero que no existe. Esto intencionadamente crea un error o un condición de excepción, escribe el código del bloque catch que maneja la condición.
|
La mejor forma de manejar la condición es: |
|
|