Download archivos

Document related concepts
no text concepts found
Transcript
Java: Archivos
Indice
Índice
• Introducción
• Manejo básico de archivos
• Archivos properties
Indice
2
Introducción
Indice
Introducción (I)
•
•
Cualquier programa realizado en Java que necesite llevar a cabo una operación de
I/O lo hará a través de un stream.
Un stream, cuya traducción literal es "flujo", es una abstracción de todo aquello que
permite introducir o extraer información. 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

Indice
La vinculación de este stream al dispositivo físico (teclado, pantalla, archivo,
impresora, etc.) la hace el sistema de entrada y salida de Java.
4
Introducción (II)
•
El paquete System define tres clases:
–
–
–
•
in (entrada estándar)
out (salida estándar)
err (salida de errores estándar)
La escritura hacia pantalla se hace con System.out
System.out.println(“Hola Mundo”); // Añade nueva línea al final
System.out.print(“Adios”);
// NO añade nueva línea al final
•
La lectura desde teclado se hace con System.in
•
Para archivos tendremos flujos de:
–
–
Indice
Entrada (input stream), lectura de archivo
Salida (output stream), escritura de archivo
5
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 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 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 método read() para leer caracteres. Pero todavía
no es suficiente. Necesitamos otras clases que conviertan el flujo en modo carácter a
uno en modo buffer (una cadena de caracteres con señal de fin de línea). 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 (byte-carácter-buffer) se encuentra en el manejo de teclado:
BufferedReader entrada = new BufferedReader(new InputStreamReader(System.in));
entrada.readLine();
Indice
Flujo de bytes
Flujo de caracteres
Flujo de buffer
InputStream
InputStreamReader
BufferredReader
6
Manejo básico de archivos
Indice
Del byte al buffer con archivos
•
•
•
•
En el siguiente ejemplo con archivos partimos de un stream de bytes
(FileInputStream)
A continuación lo convertimos en un stream de caracteres (FileReader).
Pero como vamos buscando mayor abstracción (y comodidad) lo convertimos en un
flujo en modo buffer (BufferedReader)
En este ejemplo obtenemos la primera línea 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:
–
–
–
–
Indice
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 podrían utilizar rutas relativas en función de la
configuración del IDE
fis.getFD(): me devuelve el descriptor de archivo (FileDescriptor)
8
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 tamaño, 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 línea: " + linea);
} catch (Exception e) {
e.printStackTrace();
}
•
Indice
Consulte la documentación del JDK, ya que que con File se pueden hacer más cosas: crear
directorios, borrar, obtener listas de archivos, etc.
9
Listado filtrado de archivos (I)
•
En este ejemplo se obtienen todos los archivos de un directorio, que tengan una
extensión determinada (java). Nuestro método “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 continuación en nuestro método creamos un objeto del tipo File que hace referencia
al directorio
Después llamamos al método 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
métodos del interfaz. En nuestro caso el método accept(). Este método devuelve true si el archivo
(parámetro) 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 capítulos 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 método “lectura()”, que por ahora sólo
muestra por pantalla cada línea 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( "Línea: " + linea);
} catch (Exception e) {
e.printStackTrace();
}
}
•
En el for() lo primero que hacemos es leer la primera línea. Siempre comprobamos que lo que devuelve
readLine() no es null o vacío.
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
• Ejemplo:
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() );
• En este ejemplo se puede observar que StringTokenizer implementa
countTokens(), que nos devuelve el número de tokens disponibles. Es
necesario insistir en la palabra “disponible”, ya que la segunda llamada a
este método devuelve cero (ya se ha llegado al final y no hay ningún 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.*;
Vamos a enriquecer el ejemplo de las figuras, tratando de crear
instancias de la clase Circulo por cada línea 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
import java.io.File;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.StringTokenizer;
•
Vamos a usar el StringTokenizer, para tratar cada línea. Si hay
algún error en una línea, no se crea la figura
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
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;
Los try-catch internos controlan que, en caso de error en
una conversión (parseXX()), no se detenga la ejecución del
programa
Antes de acabar el for() que recorre las líneas: si no hay
errores, creamos el círculo y lo agregamos a la página
Al final se devuelve la página (si no se ha podido leer el
archivo, devuelve null)
if (st.hasMoreElements()) {
try {
x = Integer.parseInt((String) st.nextElement());
} catch (Exception e) {}
}
//// Creamos la figura si no hay errores
if (st.hasMoreElements()) {
if (clase != null && posicion != null && radio != -1) {
try {
circulo = new Circulo(radio, posicion);
y = Integer.parseInt((String) st.nextElement());
pagina.agregar(circulo);
} catch (Exception e) {}
}
}
} // FIN DE FOR
if (x != -1 && y != -1)
posicion = new Punto(x, y);
} catch (Exception e) {
e.printStackTrace();
//// Obtenemos el radio
return null;
double radio = -1;
}
if (st.hasMoreElements()) {
return pagina;
try {
radio = Double.parseDouble((String) st.nextElement());
Indice
} catch (Exception e) {}
}
}
}
15
Segundo ejemplo (III)
•
El método main() es muy breve debido al grado de encapsulamiento de la aplicación:
–
–
Si falla la lectura del archivo : la página puede ser null
Una precaución: para gestionar el caso en el que la página sea null, el método VistaFiguras.mostrar() es:
public static void mostrar( Pagina pag ) {
if ( pag == null ) {
System.out.println("Error al intentar mostrar la página");
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 lógica de streams de byte-carácter-buffer
Usamos:
–
–
–
•
write( String ): escribe la cadena en el flujo
newLine(): escribe señal de nueva línea en el flujo
close(): vierte (flush) el contenido del flujo en el archivo y lo cierra
Seguimos con el ejemplo de las figuras. Implementamos el método que obtiene las figuras (sólo círculos) de la
página 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));
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;
completo
} catch (Exception e) {
return false;
}
Indice
}
17
Archivos properties
Indice
Las propiedades
• Java incorpora estructuras de datos en la forma
de propiedad=valor, usando archivos con
extensión .properties
• Normalmente sirven para información de
configuración
• Ejemplo:
directorio= c:/DOC/Java_libre/Figuras/src/figuras/dominio
extension=java
Indice
• Ventaja: podremos cambiar el directorio y
extensión en el archivo properties, sin
necesidad de cambiar y recompilar el código
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
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;
}
}
/*** Método que recupera el valor de una propiedad o clave del atributo 'prop'. Si no la encuentra, devuelve el parámetro '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