Acceso a datos

72
ACCESO A DATOS

Transcript of Acceso a datos

Page 1: Acceso a datos

ACCESO A DATOS

Page 2: Acceso a datos

INTRODUCCIÓN

El módulo Acceso a Datos se desarrollará a lo largo de este curso con una duración de 6 horas semanales. El alumno aprenderá a desarrollar aplicaciones que gestionen la información almacenada en ficheros, bases de datos y XML, y la utilización de herramientas de mapeo objeto relacional (ORM).

Page 3: Acceso a datos

CONTENIDOS

El módulo Acceso a Datos está distribuido en 6 unidades de trabajo, distribuidas en dos evaluaciones, que se detallan a continuación:

Primera evaluación:

1. Programación avanzada PL/SQL. Bases de datos relacionales y orientadas a objetos.

2. Bases de datos XML

Segunda evaluación:

3. Manejo de ficheros

4. Herramientas de mapeo objeto relacional

5. Manejo de conectores

6. Programación de componentes de acceso a datos

Page 4: Acceso a datos

RECURSOS

Para el desarrollo y aprendizaje del módulo Acceso a datos vamos a necesitar un compilador de Java para el desarrollo de los ejercicios prácticos propuestos.

El entorno de desarrollo que vamos a utilizar es Eclipse, por ser un entorno de desarrollo libre muy potente.

Page 5: Acceso a datos

UT 3. MANEJO DE FICHEROS

1. Introducción

2. Formas de acceso a un fichero. Clases asociadas

3. Flujos o Streams. Tipos.

4. Formas de acceso a un fichero

5. Operaciones sobre ficheros

6. Clases para gestión de flujos de datos desde/hacia ficheros

7. Trabajo con ficheros XML (Extended Markup Language)

Contenidos de la unidad

Page 6: Acceso a datos

UT 3. MANEJO DE FICHEROS

En esta unidad se muestran algunas alternativas diferentes para trabajar con ficheros. Aunque no son todas las posibles, estas soluciones pueden considerarse una referencia dentro de las soluciones actuales respecto al almacenamiento de datos en ficheros.

Aunque las diferentes alternativas de acceso a ficheros mostradas en el capítulo se han trabajado desde la perspectiva de Java, la mayoría de entornos de programación dan soporte a estas mismas alternativas, aunque con otra sintaxis (por ejemplo, Microsoft .NET).

Las primeras secciones del capítulo se centran en el acceso a ficheros desde Java (flujos). Para comprender adecuadamente estos contenidos, es recomendable que el lector esté familiarizado con conceptos básicos de programación en Java.

Las últimas secciones se centran en el manejo de XML como tipo especial de fichero.

1. Introducción

Page 7: Acceso a datos

UT 3. MANEJO DE FICHEROS

Un fichero o archivo es un conjunto de bits almacenado en un dispositivo, como por ejemplo un disco duro. Una de las ventajas de usar ficheros es que éstos no son volátiles. Los ficheros tienen un nombre y se ubican en directorios o carpetas, el nombre debe ser único en ese directorio. Por convención cuentan con diferentes extensiones que por lo general suelen ser tres letras (PDF, DOC, GIF, …) y nos permiten saber el tipo de archivo.

1. Introducción

Page 8: Acceso a datos

UT 3. MANEJO DE FICHEROS

Antes de ver las clases que leen y escriben datos en ficheros, vamos a manejar la clase File:

File es una clase dentro del paquete java.io

Representa un archivo o directorio dentro de un sistema de ficheros.

Un objeto de la clase File representa el nombre de un fichero o directorio.

Los métodos de File permiten obtener toda la información sobre las características del fichero o directorio.

2. Formas de acceso a un fichero. Clases asociadas.

Page 9: Acceso a datos

UT 3. MANEJO DE FICHEROS

Para crear un objeto File, se puede utilizar cualquiera de los tres constructores siguientes:

File(String directorioyfichero)new File(“C:\\directorio\\fichero.txt”);

File(String directorio, String nombrefichero)new File(“directorio”, “fichero.txt”);

File(File directorio, String fichero)new File(new File(“directorio”), “fichero.txt”);

2. Formas de acceso a un fichero. Clases asociadas.

Page 10: Acceso a datos

UT 3. MANEJO DE FICHEROS

El siguiente ejemplo muestra la lista de ficheros del directorio actual utilizando el método list() que devuelve un array de Strings con los nombres de los ficheros y directorios contenidos en el directorio asociado al objeto File:

import java.io.*;

public class VerDir {

public static void main (String[] args) {

System.out.println(“Ficheros en el directorio actual: “);

File f = new File(“.”);

String[] archivos = f.list();

for (int i = 0; i < archivos.length; i++) {

System.out.println(archivos[i]);

}

}

}

2. Formas de acceso a un fichero. Clases asociadas.

Page 11: Acceso a datos

UT 3. MANEJO DE FICHEROS

Algunos métodos importantes del objeto File son:

getName: devuelve el nombre del fichero o directorio.

getPath(): devuelve el camino relativo.

getAbsolutePath(): devuelve el camino absoluto del fichero/directorio.

canRead(): devuelve true si el fichero se puede leer.

canWrite(): devuelve true si el fichero se puede escribir.

length(): nos devuelve el tamaño del fichero en bytes.

createNewFile(): crea un nuevo fichero, vacío, asociado a File si y solo si no existe un fichero con dicho nombre.

2. Formas de acceso a un fichero. Clases asociadas.

Page 12: Acceso a datos

UT 3. MANEJO DE FICHEROS

delete(): borra el fichero o directorio asociado al File.

exists(): devuelve true si el fichero/directorio existe.

getParent(): devuelve el nombre del directorio padre, o null si no existe.

isDirectory(): devuelve true si el objeto File corresponde a un directorio.

isFile(): devuelve true si el objeto File corresponde a un fichero normal.

mkdir(): crea un directorio con el nombre indicado en la creación del objeto File.

renameTo(File nuevonombre): renombra el fichero.

2. Formas de acceso a un fichero. Clases asociadas.

Page 13: Acceso a datos

UT 3. MANEJO DE FICHEROS

Ejemplos de uso de la clase Clase File.

Código para la creación de un objeto File con un fichero llamado libros.xmlFile f = new File(“proyecto\\libros.xml”);

Ejemplo de uso del objeto FileSystem.out.println (“Nombre: “ + f.getName());

System.out.println (“Directorio padre: “ + f.getParent());

System.out.println (“Ruta relativa: “ + f.getPath());

System.out.println (“Ruta absoluta: “ + f.getAbsolutePath());

2. Formas de acceso a un fichero. Clases asociadas.

Page 14: Acceso a datos

UT 3. MANEJO DE FICHEROS

En Java, el acceso a ficheros es tratado como un flujo de información entre el programa y el fichero. Un flujo no es más que un objeto que hace de intermediario entre el programa y el origen o el destino de la información. Esta abstracción proporcionada por los flujos hace que los programadores, cuando quieren acceder a información, solo se tengan que preocupar por trabajar con los objetos que proporcionan el flujo, sin importar el origen o el destino concreto de donde vengan o vayan los datos.

Cualquier programa que tenga que obtener información de cualquier fuente necesita abrir un stream, igualmente si necesita enviar información abrirá un stream y se escribirá la información.

La vinculación de este stream con el dispositivo físico la hace el sistema de entrada/salida de Java.

3. Flujos o Streams. Tipos.

Page 15: Acceso a datos

UT 3. MANEJO DE FICHEROS

Tenemos dos tipos de flujos:

Flujos de bytes (8 bits): su uso está orientado a la lectura/escritura de datos binarios. Todas las clases de flujos de bytes descienden de las clases InputStream y OutputStream.

Flujos de caracteres (16 bits): realizan operaciones de entrada y salida de caracteres. El flujo de caracteres viene gobernado por las clases Reader y Writer.

3. Flujos o Streams. Tipos.

Page 16: Acceso a datos

UT 3. MANEJO DE FICHEROS

InputStreamFileInputStream

PipedInputStream

FilterInputStreamLineNumberInputStream

DataInputStream

BufferedInputStream

PushbackInputStream

ByteArrayInputStream

SequenceInputStream

StringBufferInputStream

3.1. Flujos de bytes.OutputStream

FileOutputStream

PipedOutputStream

FilterOutputStream

PrintStream

DataOutputStream

BufferedOutputStream

ByteArrayOutputStream

Page 17: Acceso a datos

UT 3. MANEJO DE FICHEROS

ReaderInputStreamReader

FileReader

CharArrayReader

BufferedReader

LineNumberReder

FilterReader

PushbackReader

PipedReader

StringReader

3.2. Flujos de caracteres.Writer

OutputStreamReader

FileWriter

CharArrayWriter

BufferedWriter

FilterWriter

PipedWriter

StringWriter

PrintWriter

Page 18: Acceso a datos

UT 3. MANEJO DE FICHEROS

Hay dos formas de acceso a la información almacenada en un fichero:

Acceso secuencial: los datos o registros se leen y se escriben en orden. Si se quiere acceder a un dato es necesario leer antes todos los anteriores. La escritura de datos se hace a partir del último dato escrito, no es posible hacer inserciones entre los datos que ya hay escritos.

Acceso directo o aleatorio: permite acceder directamente a un datos o registro sin necesidad de leer los anteriores y se puede acceder a la información en cualquier orden. Los datos están almacenados en registros de tamaño conocido y nos podemos mover de un registro a otro de forma aleatoria para leerlos o modificarlos.

4. Formas de acceso a un fichero.

Page 19: Acceso a datos

UT 3. MANEJO DE FICHEROS

Acceso a ficheros

Acceso secuencial

Datos de texto

FileReaderFileWriter

Datos binarios

FileInputStreamFileOutputStream

Acceso aleatorio

RandomAccessFile

4. Formas de acceso a un fichero

Page 20: Acceso a datos

UT 3. MANEJO DE FICHEROS

Operaciones básicas sobre ficheros:

Creación del fichero.

Apertura del fichero.

Cierre del fichero

Lectura de los datos del fichero

Escritura de los datos en el fichero

5. Operaciones sobre ficheros.

Page 21: Acceso a datos

UT 3. MANEJO DE FICHEROS

En los ficheros secuenciales los registros se insertan en orden cronológico. Si hay que añadir nuevos registros éstos se añaden a partir del final del fichero:

Consultas: .para consultar un determinado registro es necesario empezar la lectura desde el primer registro, y continuar leyendo secuencialmente hasta localizar el registro buscado.

Altas: las altas se realizan al final del último registro insertado, sólo se permite añadir datos al final del fichero.

Bajas: para dar de baja un registro es necesario hacer uso de un fichero auxiliar, leyendo todos los registros y copiarlos todos a excepción del que queramos dar de baja. Por último renombraremos el fichero auziliar dándole el nombre del fichero original.

Modificaciones: El proceso de modificaciones es similar al de bajas.

5.1. Operaciones sobre ficheros secuenciales.

Page 22: Acceso a datos

UT 3. MANEJO DE FICHEROS

Normalmente para posicionarnos en un registro es necesario aplicar una función de conversión que usualmente tiene que ver con el tamaño del registro y con la clave del mismo. Veamos cómo se realizan las operaciones típicas:

Consultas: .para consultar un determinado registro necesitamos saber su clave y aplicar la función de conversión para obtener la dirección del registro que queremos leer.

Altas: para insertar un registro necesitamos saber su clave, aplicar la función de conversión a la clave para obtener la dirección y escribir el registro en la posición devuelta. Si la posición está ocupada por otro registro, el registro se insertaría en la zona de excedentes.

Bajas: para realizar las bajas se suele utilizar un campo del registro a modo de switch que tenga el valor 1 cuando el registro exista y le damos el valor 0 para darle de baja. Físicamente el registro no desaparece del disco.

Modificaciones: Para modificar un registro hay que localizarlo, modificar los datos que nos interesen y reescribir el registro en esa posición.

5.2. Operaciones sobre ficheros aleatorios.

Page 23: Acceso a datos

UT 3. MANEJO DE FICHEROS

Clase FileReader

El flujo FileReader permite leer caracteres desde un fichero de modo secuencial. Esta clase hereda los métodos de la clase Reader. Los constructores principales son:

FileReader(String ruta)

FileReader(File fichero)

El fichero puede abrirse con una ruta de directorios o con un objeto de tipo File.

Al usar la clase FileReader se puede generar la excepción FileNotFoundException.

6.1. Clases para gestión de flujos de datos. Ficheros de Texto.

Page 24: Acceso a datos

UT 3. MANEJO DE FICHEROS

Clase FileReader

Los métodos que proporciona la clase FileReader son los siguientes: int read(): lee un carácter y lo devuelve

int read(char[] buf): lee hasta buf.length caracteres de datos de una matriz de caracteres (buf). Los caracteres leídos se van almacenando en buf.

int read(char[] buf. Int desplazamiento, int n): lee hasta n caracteres de datos de la matriz buf comenzando por buf[desplazamiento] y devuelve el número leído de caracteres.

6.1. Clases para gestión de flujos de datos. Ficheros de Texto.

Page 25: Acceso a datos

UT 3. MANEJO DE FICHEROS

Clase FileReader import java.io.*;

public class LeerFichTexto {

public static void main (String[] args) throws IOException {

//declarar fichero

File fichero = new File(“C:\\EJERCICIOS\\LeerFicheroTexto.java”);

FileReader fic = new FileReader(fichero); //Crear el flujo de entrada

int i;

while ((i = fic.read()) != -1) //Se va leyendo un carácter

System.out.println((char) i);

fic.close(); //cerrar fichero

}

}

6.1. Clases para gestión de flujos de datos. Ficheros de Texto.

Page 26: Acceso a datos

UT 3. MANEJO DE FICHEROS

FileReader no contiene métodos que nos permitan leer líneas completas, pero BufferedReader sí; dispone del método readLine() que lee una línea del fichero y la devuelve, o devuelve null si no hay nada que leer o llegamos al final del fichero. Para construir un BufferedReader necesitamos la clase FileReader:

BufferedReader fichero = new BufferedReader(new FileReader(NombreFichero));

6.1. Clases para gestión de flujos de datos. Ficheros de Texto.

Page 27: Acceso a datos

UT 3. MANEJO DE FICHEROS

Clase FileWriter

El flujo FileWriter permite escribir caracteres en un fichero de modo secuencial. Esta clase hereda los métodos necesarios para ello de la clase Writer. Los constructores principales son:

FileWriter (String ruta, boolean añadir)

FileWriter(File fichero)

El parámetro ruta indica la localización del archivo en el sistema operativo. El parámetro añadir igual a true indica que el fichero se usa para añadir datos a un fichero ya existente.

6.1. Clases para gestión de flujos de datos. Ficheros de Texto.

Page 28: Acceso a datos

UT 3. MANEJO DE FICHEROS

Clase FileWriter

Los métodos que proporciona la clase FileWriter son: void write(int c): escribe un carácter

void write(char[] buf): escribe un array de caracteres

void write(char[] buf, int desplazamiento, int n): escribe n caracteres de datos en la matriz buf y comenzando por buf[desplazamiento].

void write(String str): escribe una cadena de caracteres

append(char c): añade un carácter a un fichero

Estos métodos también pueden lanzar la excepción IOException.

6.1. Clases para gestión de flujos de datos. Ficheros de Texto.

Page 29: Acceso a datos

UT 3. MANEJO DE FICHEROS

La clase BufferedWriter también deriva de la clase Writer. Esta clase añade un buffer para realizar una escritura eficiente de caracteres. Para construir un BufferedWriter necesitamos un FileWriter:

BufferedWriter fichero = new BufferedWriter(new FileWriter(NombreFichero));

La clase PrintWriter posee los métodos print(String) y println(String) para escribir en un fichero. Ambos reciben un String y los escriben en un fichero, el segundo método salta de línea. Para escribir un PrintWriter necesitamos la clase FileWriter:

PrintWriter fichero = new PrintWriter(new FileWriter(NombreFichero));

6.1. Clases para gestión de flujos de datos. Ficheros de Texto.

Page 30: Acceso a datos

UT 3. MANEJO DE FICHEROS

Los ficheros binarios almacenan secuencias de dígitos binarios que no son legibles directamente por el usuario como ocurría con los ficheros de texto. Tienen la ventaja de que ocupan menos espacio en el disco. En Java, las dos clases que nos permiten trabajar con ficheros binarios son FileInputStream y FileOutputStream.

6.2. Clases para gestión de flujos de datos. Ficheros binarios.

Page 31: Acceso a datos

UT 3. MANEJO DE FICHEROS

Clase FileInputStream

El flujo FileInputStream permite leer bytes en un fichero de manera secuencial. Sus constructores tienen los mismos parámetros que los mostrados para FileReader.

Los métodos que proporciona la clase FileInputStream son similares a los vistos para FileReader. Estos métodos devuelven el número de bytes leídos o -1 si se ha llegado al final del fichero:

int read()

int read(byte[] b)

int read(byte[] b, int desplazamiento, int n)

6.2. Clases para gestión de flujos de datos. Ficheros binarios.

Page 32: Acceso a datos

UT 3. MANEJO DE FICHEROS

Clase FileOutpuStream

El flujo FileOutputStream permite escribir bytes en un fichero de manera secuencial. Sus constructores tienen los mismos parámetros que los mostrados para FileWriter: el fichero puede ser abierto vacío o listo para añadirle datos a los que ya contenga.

Los métodos que proporciona la clase FileOutputStream son: void write(int b)

void write(byte[] b)

void write(byte[] b, int desplazamiento, int n)

6.2. Clases para gestión de flujos de datos. Ficheros binarios.

Page 33: Acceso a datos

UT 3. MANEJO DE FICHEROS

Para leer y escribir datos de tipos primitivos: int, float, long,… usaremos las clases DataInputStream y DataOutputStream. Estas clases además de los métodos read() y write() proporcionan otros métodos de lectura y escritura:

6.2. Clases para gestión de flujos de datos. Ficheros binarios.

MÉTODOS PARA LECTURA MÉTODOS PARA ESCRITURAboolean readBoolean();byte readByte();int readUnsignedByte();int readUnsignedShort();short readShort();char readChar();int readInt();long readLong();float readFloat();double readDouble();String readUTF();

void writeBoolean(boolean v);void writeByte(int v);void writeUnsignedByte(String s);void writeShort(int v);void writeChars(String s);void writeChar(int v);void writeInt(int v);void writeLong(long v);void writeFloat(float v);void writeDouble(doublé v);void writeUTF(String str);

Page 34: Acceso a datos

UT 3. MANEJO DE FICHEROS

Para abrir un objeto DataInputStream lo haremos de la siguiente forma:

File fichero = new File(“nombrefichero”);

FileInputStream filein = new FileInputStream(fichero);

DataInputStream dataIS = new DataInputStream(filein);

Para abrir un objeto DataOutputStream lo haremos de la siguiente forma:

File fichero = new File(“nombrefichero”);

FileOutputStream fileout = new FileOutputStream(fichero);

DataOutputStream dataOS = new DataOutputStream(fileout);

6.2. Clases para gestión de flujos de datos. Ficheros binarios.

Page 35: Acceso a datos

UT 3. MANEJO DE FICHEROS

OBJETOS SERIALIZABLES

Con lo visto hasta ahora, si, por ejemplo, tenemos un objeto de tipo empleado con varios atributos (nombre, dirección, salario, departamento,…) y queremos guardarlo en un fichero, tendríamos que guardar cada atributo que forma parte del objeto por separado. Java nos permite guardar objetos en ficheros binarios; para poder hacerlo, el objeto tiene que implementar la interfaz Serializable que dispone de una serie de métodos con los que podremos guardar y leer objetos en ficheros binarios. Los más importantes son:

void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException: para leer un objeto.

void writeObject(java.io.ObjecOutputStream stream) throws IOException: para escribir un objeto.

Para leer y escribir objetos serializables a un stream se utilizan las clases Java ObjectInputStream y ObjectOutputStream respectivamente.

6.2. Clases para gestión de flujos de datos. Ficheros binarios. Objetos serializables.

Page 36: Acceso a datos

UT 3. MANEJO DE FICHEROS

OBJETOS SERIALIZABLES

A continuación se muestra la clase Persona que implementa la interfaz Serializable y que utilizaremos para escribir y leer objetos en un fichero binario.

6.2. Clases para gestión de flujos de datos. Ficheros binarios. Objetos serializables.

Page 37: Acceso a datos

UT 3. MANEJO DE FICHEROS

OBJETOS SERIALIZABLES

El siguiente ejemplo escribe objetos Persona en un fichero. Necesitamos crear un flujo de salida FileOutputStream y a continuación se crea el flujo de salida ObjectOutputStream, que es el que procesa los datos.

El método writeObject() escribe los objetos al flujo de salida y los guarda en un fichero.

6.2. Clases para gestión de flujos de datos. Ficheros binarios. Objetos serializables.

Page 38: Acceso a datos

UT 3. MANEJO DE FICHEROS

OBJETOS SERIALIZABLES

Para leer objetos Persona de un fichero necesitamos el flujo de entrada a disco FileInputStream y a continuación crear el flujo de entrada ObjectInputStream, que es el que procesa los datos.

El método readObject() lee los objetos del flujo de entrada y puede lanzar la excepción ClassNotFoundException.

6.2. Clases para gestión de flujos de datos. Ficheros binarios. Objetos serializables.

Page 39: Acceso a datos

UT 3. MANEJO DE FICHEROS

OBJETOS SERIALIZABLES

ObjectOutputStream puede darnos algunos problemas, por ejemplo, si escribimos datos en el fichero y lo cerramos. Después volvemos a abrirlo para añadir datos y entonces se escribe una nueva cabecera al final de los objetos introducidos anteriormente y después se van añadiendo el resto de los datos. Esto origina el problema que al leer el fichero se produzca la excepción StreamCorruptedException.

6.2. Clases para gestión de flujos de datos. Ficheros binarios. Objetos serializables.

Page 40: Acceso a datos

UT 3. MANEJO DE FICHEROS

Java dispone de la clase RandomAccessFile que contiene métodos para acceder al contenido de un fichero binario de forma aleatoria y para posicionarnos en una posición concreta del mismo.

Disponemos de dos posibilidades para crear el fichero de acceso aleatorio:

Escribiendo el nombre del fichero:

fichero = new RandomAccessFile(String nombre, String modoAcceso);

Con un objeto File:

fichero = new RandomAccessFile(File fich, String modoAcceso);

El argumento modoAcceso puede ser “r” para solo lectura o “rw” para lectura y escritura.

La clase RandomAccessFile maneja un puntero que indica la posición actual en el fichero. Cuando el fichero se crea el puntero se coloca en 0. Las sucesivas llamadas a los métodos read() y write() ajustan el puntero según la cantidad de bytes leídos o escritos.

6.3. Ficheros de acceso aleatorio.

Page 41: Acceso a datos

UT 3. MANEJO DE FICHEROS

Los métodos más importantes son:

long getFilePointer(): devuelve la posición actual del puntero del fichero.

void seek(long posicion): coloca el puntero del fichero en una posición determinada desde el comienzo del mismo.

long length(): devuelve el tamaño del fichero en bytes. La posición length() marca el final del fichero.

int skipBytes(int desplazamiento): desplaza el puntero desde la posición actual el número de bytes indicados en desplazamiento.

6.3. Ficheros de acceso aleatorio.

Page 42: Acceso a datos

UT 3. MANEJO DE FICHEROS

A continuación vamos a ver un ejemplo de un programa que escribe un fichero aleatorio con los datos de empleados, teniendo en cuenta las siguientes consideraciones:

Los datos a insertar son: apellido, departamento y salario.

Los datos se van introduciendo de forma secuencial, no se usará el método seek().

Por cada empleado también se insertará un identificador que coincidirá con el índice +1 con el que se recorren los arrays

La longitud del registro de cada empleado es la misma (36 bytes) y los tipos que se insertan y su tamaño en bytes es el siguiente:

Identificador: es un entero, ocupa 4 bytes

Apellido: cadena de 10 caracteres. Cada carácter Unicode ocupa 2 bytes, luego el apellido ocupa 20 bytes

Departamento: es un entero, ocupa 4 bytes.

Salario: es un doublé, ocupa 8 bytes.

Nota: Tamaño de otros tipos: short (2 bytes), byte (1 byte), long (8 bytes), boolean (1 bit), float (4 bytes), etc.

6.3. Ficheros de acceso aleatorio.

Page 43: Acceso a datos

UT 3. MANEJO DE FICHEROS

6.3. Ficheros de acceso aleatorio.

Page 44: Acceso a datos

UT 3. MANEJO DE FICHEROS

6.3. Ficheros de acceso aleatorio.

Page 45: Acceso a datos

UT 3. MANEJO DE FICHEROS

Para insertar un nuevo registro aplicamos la función de conversión al identificador para calcular la posición. El siguiente código inserta un empleado con identificador 20. Se ha de calcular la posición donde irá el registro dentro del fichero (identificador -1) * 36 bytes.

6.3. Ficheros de acceso aleatorio.

Page 46: Acceso a datos

UT 3. MANEJO DE FICHEROS

El lenguaje XML (eXtended Markup Language [lenguaje de marcas extendido])

Representa la información de forma neutra, independiente del lenguaje de programación y del sistema operativo empleado.

Util en el desarrollo de aplicaciones software. Se han diseñado muchas tecnologías gracias a las posibilidades ofrecidas por XML, un

ejemplo de ellas son los servicios web. Desde un punto de vista a “bajo nivel”, un documento XML no es otra cosa que un fichero

de texto. Realmente nada impide utilizar librerías de acceso a ficheros, como las vistas en la sección anterior, para acceder y manipular ficheros XML.

Desde un punto de vista a “alto nivel”, un documento XML no es un mero fichero de texto.

7. Trabajo con ficheros XML.

Page 47: Acceso a datos

UT 3. MANEJO DE FICHEROS

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE Mensaje SYSTEM "Mensaje.dtd"> <Mensaje>

<Remitente> <Nombre>Anuska Esteban</Nombre> <Mail> anuska.informá[email protected] </Mail>

</Remitente> <Destinatario>

<Nombre>Pepito de los Palotes</Nombre><Mail>[email protected]</Mail>

</Destinatario> <Texto>

<Asunto>Este es el asunto del mensaje.

</Asunto> <Parrafo>

Este es mi documento con una estructura muy sencilla no contiene atributos ni entidades...

</Parrafo> </Texto>

</Mensaje>

7. Trabajo con ficheros XML. Estructura XML.

Page 48: Acceso a datos

UT 3. MANEJO DE FICHEROS

Este mismo documento puede ser visto de forma gráfica, para comprender mejor la estructura de un documento XML. 

7. Trabajo con ficheros XML. Estructura XML.

Mensaje

Remitente

Nombre: Anuska Esteban

Mail: anuska.informá[email protected]

Destinatario

Nombre: Pepito Palotes

Mail: [email protected]

Texto

Asunto: Este es el asunto…

Parrafo: Este es mi documento…

Page 49: Acceso a datos

UT 3. MANEJO DE FICHEROS

Son necesarias herramientas específicas (librerías) para acceder y manipular este tipo de archivos de manera potente, flexible y eficiente.

Reducen los tiempos de desarrollo de aplicaciones Optimizan los propios accesos a XML. Permiten manejar los documentos XML de forma simple y sin cargar innecesariamente el sistema. Las herramientas que leen el lenguaje XML y comprueban si el documento es válido

sintácticamente se denominan analizadores sintácticos o parsers. Los dos parsers más conocidos: DOM y SAX

7. Trabajo con ficheros XML. Parsers.

Page 50: Acceso a datos

UT 3. MANEJO DE FICHEROS

La tecnología DOM (Document Object Model) es una interfaz de programación que permite analizar y manipular dinámicamente y de manera global el contenido, el estilo y la estructura de un documento.

Para trabajar con un documento XML primero se almacena en memoria en forma de árbol con nodos padre, nodos hijo y nodos finales que son aquellos que no tienen descendientes.

Una vez creada en memoria esta estructura, los métodos de DOM permiten recorrer los diferentes nodos del árbol y analizar a qué tipo particular pertenecen. En función del tipo de nodo, la interfaz ofrece una serie de funcionalidades u otras para poder trabajar con la información que contienen.

DOM ofrece una manera de acceder a documentos XML tanto para ser leído como para ser modificado. Su único inconveniente es que en el árbol DOM se crea todo en memoria principal, por lo que si el documento XML es muy grande, la creación y manipulación de DOM sería intratable.

7.1. Trabajo con ficheros XML. Acceso a datos con DOM.

Page 51: Acceso a datos

UT 3. MANEJO DE FICHEROS

Para poder trabajar con DOM en Java necesitamos las clases e interfaces que componen el paquete org.w3c.dom y el paquete javax.xml.parsers. Estas clases ofrecen métodos para cargar documentos desde una fuente de datos.

Contiene dos clases fundamentales:

DocumentBuilder

DocumentBuilderFactory

DOM no define ningún mecanismo para generar un fichero XML a partir de un árbol DOM. Para eso usaremos el paquete javax.xml.transform que permite especificar una fuente y un resultado.

7.1. Trabajo con ficheros XML. Acceso a datos con DOM.

Page 52: Acceso a datos

UT 3. MANEJO DE FICHEROS

Los programas Java que utilicen DOM necesitan estas interfaces:

Document. Es un objeto que equivale a un ejemplar de un documento XML. Permite crear nuevos nodos en el documento.

Element. Cada elemento del documento XML tiene un equivalente en un objeto de este tipo. Expone propiedades y métodos para manipular los elementos del documento y sus atributos.

Node. Representa a cualquier nodo del documento.

NodeList. Contiene una lista con los nodos hijos de un nodo.

Attr. Permite acceder a los atributos de un nodo.

Text. Son los datos carácter de un elemento.

CharacterData. Representa a los datos carácter presentes en el documento.

DocumentType. Proporciona información contenida en la etiqueta <!DOCTYPE>

7.1. Trabajo con ficheros XML. Acceso a datos con DOM.

Page 53: Acceso a datos

UT 3. MANEJO DE FICHEROS

Vamos a ver un ejemplo en el que vamos a crear un fichero XML a partir del fichero aleatorio de empleados creado en el epígrafe anterior:

7.1. Trabajo con ficheros XML. Acceso a datos con DOM.

Page 54: Acceso a datos

UT 3. MANEJO DE FICHEROS

7.1. Trabajo con ficheros XML. Acceso a datos con DOM.

Page 55: Acceso a datos

UT 3. MANEJO DE FICHEROS

7.1. Trabajo con ficheros XML. Acceso a datos con DOM.

Page 56: Acceso a datos

UT 3. MANEJO DE FICHEROS

Para leer un documento XML, creamos una instancia de DocumentBuilderFactory para construir el pasrser y cargamos el documento con el método parse():

7.1. Trabajo con ficheros XML. Acceso a datos con DOM.

Page 57: Acceso a datos

UT 3. MANEJO DE FICHEROS

7.1. Trabajo con ficheros XML. Acceso a datos con DOM.

Page 58: Acceso a datos

UT 3. MANEJO DE FICHEROS

7.1. Trabajo con ficheros XML. Acceso a datos con DOM.

Page 59: Acceso a datos

UT 3. MANEJO DE FICHEROS

SAX (API Simple para XML) es un conjunto de clases e interfaces para el procesamiento de documentos XML.

Permite analizar los documentos de forma secuencial.

Poco consumo de memoria.

Impide tener una visión global del documento que se va a analizar.

SAX es más complejo de programar que DOM. La lectura de un documento XML produce eventos que ocasiona la llamada a métodos.

7.2. Trabajo con ficheros XML. Acceso a datos con SAX.

Page 60: Acceso a datos

UT 3. MANEJO DE FICHEROS

En la siguiente tabla podemos ver los elementos del documento XML y los métodos asociados a los eventos que producen.

7.2. Trabajo con ficheros XML. Acceso a datos con SAX.

Page 61: Acceso a datos

UT 3. MANEJO DE FICHEROS

Vamos a ver un ejemplo sencillo en Java que muestra los pasos básicos necesarios para hacer que se puedan tratar los eventos.

7.2. Trabajo con ficheros XML. Acceso a datos con SAX.

Page 62: Acceso a datos

UT 3. MANEJO DE FICHEROS

7.2. Trabajo con ficheros XML. Acceso a datos con SAX.

Page 63: Acceso a datos

UT 3. MANEJO DE FICHEROS

Serialización: Transforma los objetos Java en documentos XML en el disco.

Deserialización: Lee el fichero XML interpretándolo y generando los objetos.

Para serializar objetos Java a XML y viceversa utilizaremos la librería Xstream. Para ello necesitaremos descargar los JAR desde http://xstream.codehaus.org/download.html

Necesitaremos el fichero xstream.1.4.6.jar y el fichero kxml2-2.3.0.jar que se puede descargar desde el apartado Optional Dependencies.

7.3. Serialización de objetos a XML

Page 64: Acceso a datos

UT 3. MANEJO DE FICHEROS

En el siguiente ejemplo, vamos a serializar un objeto Java, creando un fichero XML. Partiremos del fichero Persona.dat para crear el objeto y a continuación usaremos la clase Xstream para crear el fichero XML.

7.3. Serialización de objetos a XML

Page 65: Acceso a datos

UT 3. MANEJO DE FICHEROS

7.3. Serialización de objetos a XML

Page 66: Acceso a datos

UT 3. MANEJO DE FICHEROS

7.3. Serialización de objetos a XML

Page 67: Acceso a datos

UT 3. MANEJO DE FICHEROS

El fichero generado tendrá el siguiente aspecto

7.3. Serialización de objetos a XML

Page 68: Acceso a datos

UT 3. MANEJO DE FICHEROS

A continuación se muestra el código utilizado para la deserialización:

7.3. Serialización de objetos a XML

Page 69: Acceso a datos

UT 3. MANEJO DE FICHEROS

Un excepción es un evento que ocurre durante la ejecución del programa que interrumpe el flujo normal de las sentencias. Cuando no es capturada por el programa, se captura por el gestor de excepciones por defecto que devuelve un mensaje y detiene el programa.

Las excepciones en Java son objetos de clases derivadas de la clase base Exception que a su vez es una clase derivada de la clase base Throwable.

8. Excepciones: Detección y Tratamiento

Page 70: Acceso a datos

UT 3. MANEJO DE FICHEROS

Para capturar una excepción se utiliza el bloque try-catch. Se encierra en el bloque try el código que puede generar una excepción, este bloque va seguido por uno o más bloques catch. Cada bloque catch especifica el tipo de excepción que puede atrapar y contiene un manejador de excepciones. Después del último bloque catch puede aparecer un bloque finally que siempre se ejecuta haya ocurrido o no la excepción.

Para capturar cualquier excepción utilizaremos la clase base Exception. Si se usa habrá que ponerla al final de la lista de manejadores para evitar que los manejadores que vienen después queden ignorados.

8.1. Capturar excepciones

Page 71: Acceso a datos

UT 3. MANEJO DE FICHEROS

Para obtener más información sobre la excepción se puede llamar a los métodos de la clase base Throwable, algunos son:

String getMessage(): devuelve la cadena de error del objeto.

String getLocalizedMessage(): crea una descripción local de este objeto.

String toString(): devuelve una breve descripción del objeto.

void printStackTrace(), printStackTrace(PrintStream) o printStackTrace(PrintWriter): imprime el objeto y la traza de la pila de llamadas lanzada.

8.1. Capturar excepciones

Page 72: Acceso a datos

UT 3. MANEJO DE FICHEROS

Para especificar excepciones utilizamos la palabra clave throw, seguida de la lista de todos los tipos de excepciones potenciales; si un método decide no gestionar una excepción mediante try-catch, debe especificar que puede lanzar esa excepción.

Aquellos métodos que pueden lanzar excepciones deben saber cuáles son esas excepciones en su declaración. Una forma de saberlo es compilando el programa, de esta forma nos aparecerán errores indicando las excepciones que no han sido declaradas o capturadas.

8.2. Especificar excepciones