Leer los archivos de texto

(Febrero de 2005)

Introducción

Las entradas y salidas (E/S) en Java utilizan streams (secuencias o flujos). Un flujo representa una corriente de datos con (al menos) un escritor y un lector. Por ejemplo, cuando leemos del teclado estamos usando una corriente de entrada donde el programa es el lector.

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 demás clases de flujo de entrada y proporciona una interfaz básica. El sistema Java incluye un InputStream básico para entradas por teclado: System.in.

Pero necesitamos algo más sofisticado que un sistema de lectura de bytes sin estructura. Para ello vamos a utilizar flujos "filtro" que sirven de intermediarios: manejan un flujo de entrada de bytes y lo convierten en flujos estructurados (modo caracter). Un ejemplo de filtro 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 método read() para leeer caracteres. Pero todavía no es suficiente. Necesitamos otros "puentes" que conviertan el flujo en modo carácter a uno en modo buffer (una especie de cadena de caracteres). 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 método como readLine() que lee los caracteres hasta encontrar un final de línea. Un ejemplo de estas transformaciones (de flujo de byte a flujo de carácter y de éste a buffer) se encuentra en el manejo de teclado:


	BufferedReader entrada = new BufferedReader(new InputStreamReader(System.in));
	entrada.readLine();
	

Archivos y URL

Lo que hemos visto aplicado a un flujo de teclado es aplicable a los archivos. En el siguiente ejemplo el flujo de entrada es un archivo (clase java.io.File):


    File f = new File( "esto.txt" );
    BufferedReader entrada = new BufferedReader( new FileReader( f ) );
    if ( f.exists() )
		entrada.readLine();    
	

Pero en nuestro caso vamos a manejarnos en un contexto web, por tanto nos interesa usar una URL (Uniform Resource Locator). Una URL apunta a un recurso, que es una forma genérica para hablar de un objeto en espacio web (un archivo, un directorio, un host, un servidor, etc.):


	    URL url = new URL( "archivo.txt" );                     // Abro URL
	    InputStream is = url.openStream();                      // Abro InputStream desde URL
	    BufferedReader di = new BufferedReader(new InputStreamReader( is ));
	    di.readLine();
	

El problema en primer lugar es situar al archivo con respecto al applet. Para ello nos vamos a ayudar de una serie de métodos de la clase Applet:

A continuación puede ver el código fuente de un applet que usa estos métodos (editor es un objeto de la clase TextArea):


   private void jbInit() throws Exception {
      editor.setBackground( Color.orange );
      editor.append( "getName(): " + this.getName() + "\n" );
      editor.append( "getClass().getName(): " + getClass().getName() + "\n" );
      editor.append( "Protocol: " + this.getDocumentBase().getProtocol() + "\n");
      editor.append( "CodeBase (getFile): " + this.getCodeBase().getFile() + "\n");
      editor.append( "CodeBase (toString): " + this.getCodeBase().toString() + "\n");
      editor.append( "DocumentBase (getFile): " + this.getDocumentBase().getFile() + "\n");
      editor.append( "DocumentBase (toString): " + this.getDocumentBase().getFile() + "\n");
      editor.append( "Habrá podido ver que getCodeBase().getFile() y getCodeBase().toString()" +
		     " no dan el mismo resultado\n\n");

      /*** Obtengo la URL, si no se encuentra el recurso, entonces la url es null ***/
      URL url = getClass().getResource("applet_informador.class");
      if (url == null)
	 editor.append( "Don´t find Resource applet_informador.class. \n");
      else
	 editor.append( "Resource (\"applet_informador.class\"): " + url.toString() + "\n");
      editor.append( "getClass().getResource(\"xx\") tiene como directorio de referencia el del applet\n\n");

      /******* Lee el archivo de código fuente y lo escribe en el editor *********/
      editor.append( "CODIGO FUENTE:\n");
      if ( !leer_archivo( "codigo_fuente/applet_informador.java", editor) )
	 editor.append( "No he podido abrir el archivo de código fuente");

      this.setLayout(new BorderLayout());
      this.add( editor, BorderLayout.CENTER );
   }
	

A continuación puede ver el applet (pulse aquí para obtener el código fuente). El applet presenta información del sistema de archivos y después imprime el código fuente


Ejemplo de lectura de un archivo con getCodeBase()

La lectura del archivo, una vez que se sabe lo anterior, es sencilla: partimos de getCodeBase().toString() que nos devuelve la cadena que representa la dirección de la etiqueta CODEBASE de la página HTML. Si le añadimos el nombre del archivo:


	String path_absoluto = getCodeBase().toString()+archivo
	

Entonces tenemos una cadena con la trayectoria absoluta del archivo. Lo que se hace a continuación es obtener una URL:


	URL url = new URL(getCodeBase().toString()+archivo);
	

Con un URL el resto es sencillo, no hay más que obtener un BufferedReader:


	boolean leer_archivo( String archivo, TextArea area ) {
		try {
			/****** Crea un BufferedReader a partir de la URL del archivo **********/
			URL url = new URL(getCodeBase().toString()+archivo);        // Abro URL
			InputStream is = url.openStream();                          // Abro InputStream desde URL
			BufferedReader di = new BufferedReader(new InputStreamReader(is));
			String linea;

			/***** Lee línea a línea el  archivo ... ****/
			do {
				linea = di.readLine();
				if (linea == null)
					break;
				else
					area.append( linea + "\n" );
			} while ( true );

			return true;
		}
		.... (catch: gestión de excepciones)
	

Si examina el código fuente se puede observar que no nos hemos olvidado de la gestión de excepciones.



Volver al índice