Está en la página 1de 22

Java: Archivos

ndice
Introduccin Manejo bsico de archivos Archivos properties

Indice

Introduccin

Introduccin (I)
Cualquier programa realizado en Java que necesite llevar a cabo una operacin de I/O lo har a travs de un stream. Un stream, cuya traduccin literal es "flujo", es una abstraccin de todo aquello que permite introducir o extraer informacin. As, un stream de teclado es un flujo de entrada para el programa y un stream de pantalla es un flujo de salida del programa

Input: Teclado

Output: Pantalla

La vinculacin de este stream al dispositivo fsico (teclado, pantalla, archivo, impresora, etc.) la hace el sistema de entrada y salida de Java.
Indice

Introduccin (II)
El paquete System define tres clases:
  

in (entrada estndar) out (salida estndar) err (salida de errores estndar)

La escritura hacia pantalla se hace con System.out


System.out.println(Hola Mundo); // Aade nueva lnea al final System.out.print(Adios); // NO aade nueva lnea al final

La lectura desde teclado se hace con System.in Para archivos tendremos flujos de:
 

Entrada (input stream), lectura de archivo Salida (output stream), escritura de archivo

Indice

Del byte al buffer: el ejemplo del teclado


Un flujo importante en este tipo de problemas es InputStream, que es una clase abstracta para el flujo de entradas de bytes sin estructura. Es una superclase de todas las dems clases de flujo de entrada y proporciona una interfaz bsica. El sistema Java incluye un InputStream bsico para entradas por teclado: System.in Pero necesitamos algo ms sofisticado que un sistema de lectura de bytes sin estructura. Para ello vamos a utilizar flujos que reciben un flujo de entrada de bytes y lo convierten en flujos estructurados (modo caracter). Un ejemplo es InputStreamReader, que sirve de puente desde un stream de bytes a un stream de caracteres:
InputStreamReader isr = new InputStreamReader( System.in );

Con un InputStreamReader tenemos el mtodo read() para leer caracteres. Pero todava no es suficiente. Necesitamos otras clases que conviertan el flujo en modo carcter a uno en modo buffer (una cadena de caracteres con seal de fin de lnea). Para ello contamos con clases como BufferedReader que recibe en su constructor el flujo de caracteres y maneja el flujo en la forma de buffer, con un mtodo como readLine() que lee los caracteres hasta encontrar un final de lnea. Un ejemplo de estas transformaciones (byte-carcter-buffer) se encuentra en el manejo de teclado:
BufferedReader entrada = new BufferedReader(new InputStreamReader(System.in)); entrada.readLine();
Flujo de bytes InputStream Indice Flujo de caracteres InputStreamReader Flujo de buffer BufferredReader

Manejo bsico de archivos

Del byte al buffer con archivos


En el siguiente ejemplo con archivos partimos de un stream de bytes (FileInputStream) A continuacin lo convertimos en un stream de caracteres (FileReader). Pero como vamos buscando mayor abstraccin (y comodidad) lo convertimos en un flujo en modo buffer (BufferedReader) En este ejemplo obtenemos la primera lnea del archivo y la mostramos por pantalla:
String linea; try { FileInputStream fis = new FileInputStream("c:/DOC/Java_libre/Figuras/archivos/ejemplo.txt"); BufferedReader entrada = new BufferedReader(new FileReader( fis.getFD() )); linea = entrada.readLine(); System.out.println( linea); } catch (Exception e) { e.printStackTrace(); }

Notas:
  

Usamos el paquete java.io El uso de las clases de este paquete normalmente exige el manejo de excepciones Utilizamos rutas absolutas para los archivos, aunque se podran utilizar rutas relativas en funcin de la configuracin del IDE fis.getFD(): me devuelve el descriptor de archivo (FileDescriptor)

Indice

La clase File
Lo anterior es demasiado trabajoso, se puede simplificar Trabajar con streams a bajo nivel, como hasta ahora hemos hecho, te da pocos servicios. Por ejemplo, nos puede interesar averiguar si el recurso existe, se puede leer, su tamao, etc Para ello, los creadores de Java nos han provisto de clases de utilidad, como File. Un ejemplo:
File archivo = new File("c:/DOC/Java_libre/Figuras/archivos/ejemplo.txt"); String linea; try { BufferedReader entrada = new BufferedReader(new FileReader(archivo));

if ( archivo.exists() ) System.out.println( "El archivo " + archivo.getAbsolutePath() + " existe" ); if ( archivo.canRead() ) System.out.println( "El archivo se puede leer" ); System.out.println( "Longitud: " + archivo.length()); linea = entrada.readLine(); System.out.println( "Primera lnea: " + linea); } catch (Exception e) { e.printStackTrace(); }

Consulte la documentacin del JDK, ya que que con File se pueden hacer ms cosas: crear directorios, borrar, obtener listas de archivos, etc.
Indice

Listado filtrado de archivos (I)


En este ejemplo se obtienen todos los archivos de un directorio, que tengan una extensin determinada (java). Nuestro mtodo Archivador.getArchivos() nos devuelve un array del tipo File:
File archivos[]=Archivador.getArchivos("c:/DOC/Java_libre/Figuras/src/figuras/dominio", "java"); if ( archivos != null ) for ( int i = 0; i < archivos.length; i++ ) System.out.println( archivos[i].getName());

A continuacin en nuestro mtodo creamos un objeto del tipo File que hace referencia al directorio Despus llamamos al mtodo listFiles(), que nos pide como argumento una clase que implemente el interfaz java.io.FileFilter
public static File[] getArchivos(String nomDirectorio, String extension ) { try { File dir = new File( nomDirectorio ); return dir.listFiles( new FiltroArchivos(extension)); } catch (Exception e) { e.printStackTrace(); } return null; }

Indice

10

Listado filtrado de archivos (II)


Ya sabemos que cuando una clase implementa un interfaz est obligada a implementar todos los mtodos del interfaz. En nuestro caso el mtodo accept(). Este mtodo devuelve true si el archivo (parmetro) pasa el filtro:
package figuras.persistencia; import java.io.FileFilter; public class FiltroArchivos implements FileFilter { private String extension; public FiltroArchivos( String extension ) { this.extension = extension; } public boolean accept(java.io.File f) { if (!f.isDirectory()) { String name = f.getName().toLowerCase(); return name.endsWith( extension ); } return false; } }
Indice

11

Primer ejemplo
Para nuestro proyecto de figuras (consultar captulos anteriores) vamos a incorporar la capacidad de lectura de un archivo El archivo ( ejemplo.txt ) lo pondremos en un subdirectorio ( archivos ) del directorio de proyectos. En resumen: Figuras/archivos/ejemplo.txt Crearemos la clase figuras.persistencia.Archivador con el mtodo lectura() , que por ahora slo muestra por pantalla cada lnea del archivo:
public static void lectura( String nomArchivo ) { String linea; try { File archivo = new File( nomArchivo ); BufferedReader entrada = new BufferedReader(new FileReader(archivo)); if ( !archivo.exists() || !archivo.canRead()) System.out.println( Archivo no disponible ); for (linea=entrada.readLine(); linea != null && linea.length() > 0; linea= entrada.readLine()) System.out.println( "Lnea: " + linea); } catch (Exception e) { e.printStackTrace(); } }

En el for() lo primero que hacemos es leer la primera lnea. Siempre comprobamos que lo que devuelve readLine() no es null o vaco.
Indice

12

StringTokenizer
Del paquete java.util. Lo que hace:
 

Recibe una cadena de caracteres Devuelve las subcadenas separadas por el delimitador. El delimitador por defecto es el espacio en blanco
StringTokenizer st = new StringTokenizer("this is a test"); System.out.println( st.countTokens() ); while (st.hasMoreElements()) { System.out.println( (String) st.nextElement()); } System.out.println( st.countTokens() );

Ejemplo:

En este ejemplo se puede observar que StringTokenizer implementa countTokens(), que nos devuelve el nmero de tokens disponibles. Es necesario insistir en la palabra disponible , ya que la segunda llamada a este mtodo devuelve cero (ya se ha llegado al final y no hay ningn token disponible). Existe un constructor al que se puede pasar como segundo argumento un String que representa al delimitador.

Indice

13

Segundo ejemplo (I)


package figuras.persistencia; import figuras.dominio.*; import java.io.File; import java.io.BufferedReader; import java.io.FileReader; import java.util.StringTokenizer; public class Archivador { public static Pagina lectura(String nomArchivo) { Pagina pagina = null; try { File archivo = new File(nomArchivo); BufferedReader entrada = new BufferedReader(new FileReader(archivo)); pagina = new Pagina(); String linea; if (!archivo.exists() || !archivo.canRead()) return null; StringTokenizer st; Circulo circulo = null; //// Leemos linea a linea for (linea = entrada.readLine(); linea != null && linea.length() > 0; linea = entrada.readLine()) { //// Tokenizaremos la linea

Vamos a enriquecer el ejemplo de las figuras, tratando de crear instancias de la clase Circulo por cada lnea del archivo ejemplo.txt (clase, x, y, radio):
figuras.dominio.Circulo, 23, 22, 4.5 figuras.dominio.Circulo, 11, 13, 2.21 figuras.dominio.Circulo, 45, 62, 8.99

Vamos a usar el StringTokenizer, para tratar cada lnea. Si hay algn error en una lnea, no se crea la figura

Indice

st = new StringTokenizer(linea, ", ");

El segundo argumento del constructor de StringTokenizer representa el delimitador, en nuestro caso es una coma y un espacio en blanco 14

Segundo ejemplo (II)


//// Obtenemos la clase String clase = null; if (st.hasMoreElements()) clase = (String) st.nextElement(); //// Obtenemos el punto Punto posicion = null; int x = -1, y = -1; if (st.hasMoreElements()) { try { x = Integer.parseInt((String) st.nextElement()); } catch (Exception e) {} } if (st.hasMoreElements()) { try { y = Integer.parseInt((String) st.nextElement()); } catch (Exception e) {} } if (x != -1 && y != -1) posicion = new Punto(x, y); //// Obtenemos el radio double radio = -1; if (st.hasMoreElements()) { try { radio = Double.parseDouble((String) st.nextElement()); } } } return pagina; } } // FIN DE FOR } catch (Exception e) { e.printStackTrace(); return null; //// Creamos la figura si no hay errores if (clase != null && posicion != null && radio != -1) { circulo = new Circulo(radio, posicion); pagina.agregar(circulo);

Los try-catch internos controlan que, en caso de error en una conversin (parseXX()), no se detenga la ejecucin del programa Antes de acabar el for() que recorre las lneas: si no hay errores, creamos el crculo y lo agregamos a la pgina Al final se devuelve la pgina (si no se ha podido leer el archivo, devuelve null)

Indice
}

} catch (Exception e) {}

15

Segundo ejemplo (III)


El mtodo main() es muy breve debido al grado de encapsulamiento de la aplicacin:
 

Si falla la lectura del archivo : la pgina puede ser null Una precaucin: para gestionar el caso en el que la pgina sea null, el mtodo VistaFiguras.mostrar() es: public static void mostrar( Pagina pag ) { if ( pag == null ) { System.out.println("Error al intentar mostrar la pgina"); return; } for ( int i = 0; i < pag.tamanio(); i++ ) { Figura fig = pag.obtener(i); System.out.println( fig.toString() ); } }

public static void main(String[] args) { Pagina pagina = Archivador.lectura("c:/DOC/Java_libre/Figuras/archivos/ejemplo.txt"); VistaFiguras.mostrar(pagina); }

Indice

16

Escritura de archivos
Seguimos la misma lgica de streams de byte-carcter-buffer Usamos:
  

Seguimos con el ejemplo de las figuras. Implementamos el mtodo que obtiene las figuras (slo crculos) de la pgina y las escribe en el archivo:
public static boolean escritura( Pagina pagina, String nomArchivo ) { try { if ( pagina == null ) return false; BufferedWriter salida = new BufferedWriter(new FileWriter(nomArchivo));

write( String ): escribe la cadena en el flujo newLine(): escribe seal de nueva lnea en el flujo close(): vierte (flush) el contenido del flujo en el archivo y lo cierra

Circulo cir; String linea; for ( int i = 0; i < pagina.tamanio(); i++ ) { cir = (Circulo) pagina.obtener(i); linea = cir.getClass().getName() + ", " + cir.getPosicion().getX() + ", " + cir.getPosicion().getY() + ", " + cir.getRadio(); salida.write( linea ); salida.newLine(); Con getClass().getName() obtenemos el nombre } de la clase (incluye paquete) salida.close(); return true; } catch (Exception e) { return false; } Indice }

completo

17

Archivos properties

Las propiedades
Java incorpora estructuras de datos en la forma de propiedad=valor, usando archivos con extensin .properties Normalmente sirven para informacin de configuracin Ejemplo:
directorio= c:/DOC/Java_libre/Figuras/src/figuras/dominio extension=java

Ventaja: podremos cambiar el directorio y extensin en el archivo properties, sin necesidad de cambiar y recompilar el cdigo fuente

Indice

19

Carga de propiedades (I)


Java incorpora una estructura de datos para almacenar las propiedades: la clase java.util.Properties Por un momento nos olvidamos del archivo y veamos como se crean propiedades, se incorporan a un Properties y se recuperan con String getProperty() :
java.util.Properties prop = new java.util.Properties(); prop.setProperty("directorio", "c:/DOC/Java_libre/Figuras/src/figuras/dominio"); prop.setProperty("extension", "java"); System.out.println( prop.getProperty("directorio") );

Volvamos a los archivos, cargar las propiedades en un objeto del tipo Properties es muy sencillo, simplemente tenemos que llamar al mtodo load(), que nos solicita como argumento un InputStream
Indice

20

Carga de propiedades (II)


En nuestro ejemplo hemos creado una clase especialmente pensada para cargar las propiedades de un archivo y poder consultarlas:
package figuras.persistencia; import java.util.Properties; import java.io.File; /*************************************************************************** * Lee los valores de un archivo .properties ***************************************************************************/ public class LectorPropiedades { private Properties prop = new Properties(); /*** Carga en atributo 'prop' el archivo de propiedades ***/ public boolean cargar(String archivoPropiedades) { try { File archivo = new File(archivoPropiedades); // Abro prop.load(archivo.toURL().openStream()); // Cargo propiedades return true; } catch (Exception e) { return false; } } /*** Mtodo que recupera el valor de una propiedad o clave del atributo 'prop'. Si no la encuentra, devuelve el parmetro 'defecto ***/ public String getParametro(String clave, String defecto) { String retorno = defecto; try { if (prop == null) return defecto; retorno = prop.getProperty(clave, defecto); } catch (Exception e) {} return retorno; } /*** Sobrecargado. Si no encuentra clave, devuelve " ***/ public String getParametro(String clave) { return getParametro(clave, ""); } }

Indice

21

Consulta del valor de una propiedad


Desde nuestro main() la carga y consulta de propiedades resulta bastante sencilla:
LectorPropiedades lector = new LectorPropiedades(); if ( !lector.cargar("c:/DOC/Java_libre/Figuras/archivos/configuracion.properties") ) { System.out.println( "No se ha cargado el archivo de propiedades ); return; } System.out.println( lector.getParametro("directorio") ); System.out.println( lector.getParametro("extension") );

Indice

22

También podría gustarte