• No se han encontrado resultados

Consejos para el manejo de errores

In document Java soluciones de programación (página 78-80)

La E/S de archivos plantea un desafío especial cuando se trata de manejo de errores. Hay dos razones para esto. En primer lugar, las fallas de E/S son una posibilidad muy real cuando se leen o escriben archivos. A pesar del hecho de que el hardware de computación (e Internet) es mucho más confi able que en el pasado, aún falla a una tasa muy elevada, y cualquiera de esas fallas debe manejarse de manera consistente con las necesidades de su aplicación. La segunda razón de que el manejo de errores presente un desafío cuando se trabaja con archivos es que casi todas las operaciones de archivo pueden generar una o más excepciones. Esto signifi ca que casi todo el código de manejo de archivos debe incluirse en un bloque try.

La excepción de E/S más común es IOException. Muchos constructores y métodos en el sistema de E/S pueden lanzar esta excepción. Como regla general, es generada cuando algo sale mal al leer o escribir datos, o al abrir un archivo. Otras excepciones comunes relacionadas con E/S, como FileNotFoundException y ZipException, son subclases de IOException.

Hay otra excepción común relacionada con el manejo de archivos: SecurityException. Muchos constructores o métodos lanzarán una SecurityException si la aplicación que invoca no tiene permiso para acceder a un archivo o realizar una operación específica. Necesitará manejar esta excepción de una manera apropiada para su aplicación. Por simplicidad, los ejemplos de este capítulo no manejan excepciones de seguridad, pero tal vez sea necesario que sus aplicaciones las incluyan.

Debido a que muchos constructores y métodos pueden generar una IOException, no es poco común ver código que simplemente envuelve todas las operaciones de E/S dentro de un solo bloque try y luego captura la IOException que pueda ocurrir. Aunque sea adecuado experimentar con E/S de archivo o posiblemente con simples programas de utilería que son para su propio uso personal, este método no suele ser adecuado para código comercial. Esto se debe a que no es fácil tratar de manera individual con cada posible error. En cambio, para un control detallado, es mejor poner cada operación dentro de su propio bloque try. De esta manera, puede reportar y responder de manera precisa al error que ocurrió. Este es el método demostrado por los ejemplos en este capítulo.

Otra manera en que a veces se maneja IOException es lanzarla fuera del método en que ocurre. Para esto, debe incluir una cláusula throws IOException en la declaración del método. Este método es bueno en algunos casos, porque reporta una falla de E/S al llamador. Sin embargo, en otras situaciones es un método abreviado poco satisfactorio porque causa que todos los usuarios del método manejen la excepción. Los ejemplos de este capítulo no usan este método. En cambio, manejan explícitamente todas las excepciones IOException. Esto permite que cada manejador de error reporte precisamente el error que ocurrió.

Si maneja excepciones IOException al lanzarlas fuera del método en que ocurren, debe tener un cuidado adicional en cerrar cualquier archivo que haya sido abierto por el método. La manera más fácil de hacer esto consiste en envolver el código de su método en un bloque try y luego usar una cláusula finally para cerrar los archivos antes que el método que regresa.

En los ejemplos de este capítulo, cualquier excepción de E/S que ocurra se maneja con el simple despliegue de un mensaje. Aunque este método sea aceptable para los programas de ejemplo, por lo general las aplicaciones reales necesitarán proporcionar una respuesta más sofisticada a un error de E/S. Por ejemplo, tal vez quiera dar al usuario la capacidad de volver a probar la operación, especificar una operación alterna o manejar de otra manera el problema. El objetivo principal es evitar la pérdida o corrupción de los datos. Parte de la tarea de ser un gran programador consiste en saber cómo manejar efectivamente las cosas que podrían salir mal cuando falla una operación de E/S.

Un punto final: un error común que ocurre cuando se manejan archivos consiste en olvidar el cierre de un archivo cuando se termina de usarlo. Los archivos abiertos usan recursos del sistema. Por tanto, hay límites al número de archivos que pueden abrirse en cualquier momento. El cierre de un archivo también asegura que cualquier dato escrito en el archivo se escriba realmente en el dispositivo físico. Por tanto, la regla es muy simple: si abre un archivo, ciérrelo. Aunque los archivos suelen cerrarse automáticamente cuando termina una aplicación, es mejor no depender de esto porque puede llevar a una programación deficiente y a malos hábitos. Es mejor cerrar explícitamente cada archivo, manejando de manera apropiada cualquier excepción que pudiera ocurrir. Por esto, en los ejemplos de este capítulo todos los archivos se cierran de manera explícita, aunque el programa se esté terminando.

Las dos operaciones con archivos más fundamentales son la lectura de y la escritura de bytes en un archivo. En esta solución se muestra cómo realizar la primera. (En la siguiente se muestra cómo manejar la segunda). Aunque Java ofrece la capacidad de leer otros tipos de datos, como caracteres, valores de punto fl otante o líneas de texto, la E/S de bytes es la base del manejo de archivos, porque todas las operaciones con archivos están, en esencia, orientadas a bytes. Más aún, este tipo de operaciones puede usarse con cualquier tipo de archivo, sin importar lo que contenga. Por ejemplo, si quiere escribir una utilería de archivos que despliegue la representación hexadecimal de los bytes de un archivo, entonces necesitar usar clases de E/S basadas en bytes. Esto permite que el programa cree un "volcado hexadecimal" para cualquier tipo de archivo, incluidos los que contienen texto, imágenes, código ejecutable, etcétera.

Una manera de leer bytes de un archivo consiste en usar FileInputStream. Se deriva de InputStream, que define la funcionalidad básica de todos los flujos de entrada de bytes. Implementa la interfaz Closeable.

Paso a paso

Para leer bytes de un archivo empleando FileInputStream se requieren estos pasos: 1. Abra el archivo al crear una instancia de FileInputStream.

2. Lea el archivo empleando el método read( ). 3. Cierre el archivo al llamar a close( ).

Análisis

A fi n de abrir un archivo para entrada, cree un objeto de FileInputStream, que defi ne tres constructores. El que usaremos es:

FileInputStream(String nombreArchivo) throws FileNotFoundException

Aquí, nombreArchivo especifi ca el nombre del archivo que desea abrir. Si el archivo no existe, entonces se lanza FileNotFoundException.

Para leer del archivo, puede usar cualquier versión del método read( ), que se hereda de InputStream. Aquí se muestra el que usaremos:

int read( ) throws IOException

Lee un solo byte del archivo y lo devuelve como un valor entero. read( ) devuelve –1 cuando se encuentra el final del archivo. Lanzará una IOException si ocurre un error de E/S. Otras versiones de read( ) pueden recibir como entrada varios bytes a las vez y ponerlos en una matriz.

In document Java soluciones de programación (página 78-80)