¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
  1. Libros
  2. Desarrollo informático
  3. Los workflows
Extrait - Desarrollo informático Aprenda a diseñar antes de programar
Extractos del libro
Desarrollo informático Aprenda a diseñar antes de programar Volver a la página de compra del libro

Los workflows

Objetivos del capítulo

El objetivo de este capítulo es entender la jerarquía y el funcionamiento de las clases de gestión de los workflows de Java. Además, le permitirá desarrollar aplicaciones que utilicen archivos (texto o binarios).

Definición

Los workflows permiten realizar operaciones de lectura y escritura de datos.

El origen y el destino de los datos son variados: teclado, pantalla, red, archivos, etc.

La naturaleza de los datos también es variada: binario, texto, imágenes, sonidos, etc.

Las clases de gestión de los workflows son agrupan en el paquete java.io.

Los workflows de la clase System

1. System.out

En los capítulos anteriores, las impresiones por consola se hacían usando la instrucción: 

System.out.println(); 

out es una propiedad de la clase System.

Su declaración es:

public static final PrintStream out

Es una referencia de tipo PrintStream. El objeto designado por esta referencia se instancia al inicio de la aplicación y se asigna durante la salida por consola.

La clase PrintStream deriva de OutputStream a través de FilterOutputStream:

images/1_209.png
  • La clase abstracta OutputStream representa un workflow binario de salida. Los métodos de escritura de esta clase envían uno o varias bytes a un destino de salida.

  • La clase FilterOutputStream redefine el resto de los métodos de OutputStream

  • La clase PrintStream define algunos métodos de escritura prácticos, como print() o println().

2. System.err

Como la propiedad out, la propiedad err de la clase System es de tipo PrintStream, asignada a la consola, e instanciada al inicio de la aplicación. Este workflow está especializado en la visualización de los mensajes de error.

De vez en cuando se observa una mezcla entre los mensajes de error y el resultado de los System.out.print() de nuestras aplicaciones. Esta mezcla se debe al destino común de los objetos out y err.

3. System.in

in es la última de las tres propiedades públicas de la clase System.

Su declaración...

Codificación y workflows de texto

1. Utilización del método read() de la clase InputStream

El método read() se describe de esta manera en la documentación de la clase InputStream:

public abstract int read() throws IOException

Es el método más rudimentario para leer información. Este método lee un byte a partir de una fuente de datos y devuelve el código.

El siguiente programa muestra su utilización:

public class IntroducirValor1  
{  
   public static void main(String args[]) throws IOException  
   {  
       int codigoRetorno;  
  
       System.out.print("Rellenar un carácter (después pulse Intro): ");
       codigoRetorno = System.in.read();  
       System.out.println("Byte leído (en hexadecimal): " +   
               Integer.toHexString(codigoRetorno));  
   }  
} 

El resultado de la ejecución de este programa es el siguiente:

images/4_209.png

System.in es un workflow de tipo InputStream. InputStream es un workflow binario. Esta clase y sus clases derivadas tienen métodos de lectura de bytes.

En el ejemplo anterior, cuando se introduce el carácter por el teclado, el código introducido en la variable codigoRetorno es 80, valor correspondiente a la codificación por defecto de la plataforma (Cp1252).

Pero 80 no es el código del carácter para Java, que utiliza la codificación UTF-16. En esta codificación, el carácter tiene el valor 20AC.

Para meter el código UTF-16 del carácter € escrito...

Los archivos

Los archivos utilizados en esta sección se almacenan en el directorio: C:\JAVA\Archivos

1. Clase File

La clase File hereda directamente de Object. Un objeto de esta clase contiene una representación de un archivo, independientemente del sistema operativo. El constructor de la clase File recibe argumentos que permiten localizar el archivo (directorio, nombre del archivo, ruta de acceso). Hay métodos que permiten obtener las características del archivo designado.

Ejemplo

public class VerificaFile  
{  
   public static void main(String args[]) throws IOException  
   {  
       File directorio;  
       File archivo1, archivo2; 

El objeto directorio localiza un directorio:

       directorio = new File("C:\\JAVA\\Archivos");  
       System.out.println(directorio.getAbsolutePath());  

El objeto archivo1 localiza el archivo "textoOriginal.txt" del directorio:

       archivo1 = new File(directorio, "textoOriginal.txt");  
       System.out.println(archivo1.getAbsolutePath());  

El objeto archivo2 localiza directamente el archivo textoOriginal.txt:

       archivo2 = new File("C:\\JAVA\\Archivos\\textoOriginal.txt"); 
       System.out.println(archivo2.getAbsolutePath());  
  
       System.out.println("Tamaño...

Los archivos texto

1. Copia de un archivo de texto con cambio de codificación

a. Utilización de InputStreamReader y OutputStreamWriter

En este programa, se lee el archivo de entrada carácter a carácter y se escribe tal cual en el archivo de salida.

public class CopiaTexto1  
{  
   public static void main(String args[]) throws IOException  
   {  
       . . . 
       InputStreamReader Entrada;  
       OutputStreamWriter salida;  
       int caracter;  
  
       directorio = new File("C:\\JAVA\\archivos");  
       archivoEntrada = new File(directorio, "textoCp1252.txt");  
       archivoSalida = new File(directorio, "textoUTF8.txt"); 

El archivo de texto de entrada se codifica en Cp1252, el de salida se codifica en UTF-8:

       try  
       { 
           Entrada = new InputStreamReader(  
               new FileInputStream(archivoEntrada), "Cp1252");  
           try  
           { ...

Trabajo práctico: total de las notas

1. Objetivo

  • Utilizar los workflows de texto.

  • Utilizar una clase buscando en la documentación de Java.

2. Tema

Se dispone de un archivo de texto cuyas filas contienen:

  • Un nombre.

  • Una o varias notas (enteros) separadas por puntos y coma.

Crear, a partir de este archivo, otro archivo de texto que contenga una fila por cada nombre de la forma:

  • El total de las «n» notas de «nombre» es de: «total».

Ejemplo

Para el archivo de entrada que contiene:

CUERVO;0;1;0;10;13;2;1;10  
ESTORNINO;17;2;20;14;19;20;15  
CARBONERO AZUL;1;3;2;0;11;18;1;4;2;12;7;3;1  
GORRIÓN;1;2;0;0;2;1;2;2;1;0;1;0;0;0  
GOLONDRINA;0;1;4;0;10 

Se debe obtener el archivo de salida:

El total de las 8 notas de CUERVO es de: 37  
El total de las 7 notas de ESTORNINO es de: 107  
El total de las 13 notas de CARBONERO AZUL es de: 65  
El total de las 14 notas de GORRIÓN es de: 12  
El total de las 5 notas de GOLONDRINA es de: 15 

3. Recursos

La clase StringTokenizer contiene métodos muy prácticos para aislar las diferentes palabras de una cadena de caracteres (String). Se aconseja escribir un programa de comprobación de los métodos de esta clase antes de resolver el problema anterior.

4. Total de las notas: propuesta de corrección

a. Comprobación de algunos métodos de la clase StringTokenizer

import java.util.*;  
import java.io.*;  
  
public class VerificaStringTokenizer  
{  
   public static void main(String[] args) throws IOException  ...

Trabajo práctico: archivo de texto de los contactos

1. Objetivo

  • Utilizar los workflows de texto.

  • Crear una clase Contacto: un objeto de esta clase permite almacenar la información correspondiente a un contacto.

  • Utilizar una clase del API Java buscando en la documentación. Esta utilización permite revisar la noción de interfaz.

2. Tema

En primer lugar, con un editor de texto cree un archivo de contactos llamado «contactos.txt», formado por filas de seis campos separados por ; (punto y coma).

Ejemplo

125;HURRACA;17, Calle de la igualdad;77000;MELUN;1  
314;HALCÓN;Avenida del verdor;66000;PERPIÑÁN;4  
147;TREPADOR;Calle de los 4 fenicios;66000;PERPIÑÁN;3  
. . . 

A continuación, cree un programa que permita:

  • Leer este archivo, almacenar los registros leídos en una ArrayList de objetos Contacto, cuyas propiedades son:

private Integer numero;               
private String  nombre;  
private String  direccion;  
private String  codigoPostal;  
private String  ciudad;  
private Integer codigosector; 
  • Ordenar la ArrayList por orden de número.

    Existe un método sort() en la clase Colecciones capaz de ordenar los objetos que implementan Comparable.

  • Volver a copiar la ArrayList ordenada en un archivo de texto «contactosOrdenados.txt». Las filas de este nuevo archivo tienen la misma estructura que las de «contactos.txt».

3. Ejemplo de ejecución

Archivo contactos.txt:

125;HURRACA;17, Calle de la igualdad;77000;MELUN;1  
314;HALCÓN;Avenida del verdor;66000;PERPIÑÁN;4  
147;TREPADOR;Calle de los 4 fenicios;66000;PERPIÑÁN;3  
100;CUERVO;1, Calle Barba;94000;CRETEIL;1  
110;PALOMA;100, Avenida de la montaña;75008;PARÍS;2  
217;AVOCETA;123, Avenida del general De Gaulle;92000;NANTERRE;1 

Archivo ContactosOrdenados.txt:

100;CUERVO;1, Calle Barba;94000;CRETEIL;1  
110;PALOMA;100, Avenida de la montaña;75008;PARÍS;2  
125;HURRACA;17, Calle de la igualdad;77000;MELUN;1  
147;TREPADOR;Calle de los 4 fenicios;66000;PERPIÑÁN;3  
217;AVOCETA;123, Avenida del general De Gaulle;92000;NANTERRE;1  
314;HALCÓN;Avenida del verdor;66000;PERPIÑÁN;4...

Los archivos binarios

1. Clases DataInputStream, DataOutputStream

a. Jerarquía de los workflows de entrada (extracto)

images/18_209.png

La clase FileInputStream solo dispone del método read(), que permite leer un byte o una tabla de bytes.

La clase DataInputStream tiene métodos de lectura de tipos primitivos, tales como: readInt(), readFloat(), readDouble()

b. Jerarquía de los workflows de salida (extracto)

images/19_209.png

La clase FileOutputStream solo dispone del método write(), que permite escribir un byte o una tabla de bytes.

La clase DataOutputStream tiene métodos de escritura de tipos primitivos, tales como: writeInt(), writeFloat(), writeDouble()

c. Creación de un archivo binario de enteros (int)

public class CreacionBinario  
{  
   public static void main(String args[]) throws IOException  
   {  
       . . .  
       DataOutputStream salida;  
       int n;  
       . . .  
       archivoSalida = new File(directorio, "archivo.dat");  
  
       try  
       { 

El constructor de DataOutputStream recibe un OutputStream como argumento:

           salida = new DataOutputStream(new FileOutputStream(archivoSalida));  
  
           try  
           {  
               System.out.print("Escribir un entero: ");  
               n = Teclado.readInt();  
  
               while (true)  
               {  
                   salida.writeInt(n);  
                   System.out.print("Escribir un entero: ");  
                   n = Teclado.readInt();  
               }  
           ...

Trabajo práctico: archivo binario de los contactos

1. Objetivo

El objetivo es leer en Java un archivo binario escrito en lenguaje C.

2. El archivo binario contactos.dat

El archivo contactos.dat se ha escrito por un programa C.

Cada registro de este archivo se corresponde con una variable de tipo CONTACTO.

El siguiente programa C muestra el tamaño de una variable de tipo CONTACTO en número de bytes:

typedef struct  
{  
   int numero;  
   char nombre[21];  
   char direccion[51];  
   char codigoPostal[6];  
   char ciudad[21];  
   int  codigosector;  
} CONTACTO;  
  
int main()  
{  
   printf("Tamaño registros: %d\n", sizeof(CONTACTO));  
   return 0;  
} 

A continuación se muestra el resultado de la ejecución de este programa:

images/23_209.png

La estructura tiene un byte más que el total de las longitudes de sus miembros (4 + 21 + 51 + 6 + 21 + 4 = 107). En efecto, el total de las longitudes de las cadenas situadas antes del entero codigosector es igual a 99. Un entero se sitúa en memoria en un byte, cuya dirección es un múltiplo de 4. Por lo tanto, entre el último carácter de la cadena ciudad y el primer byte de codigosector, hay un «agujero» de 1 byte que debe tenerse en cuenta para la lectura del archivo en Java.

3. Datos numéricos en C y en Java

Los datos numéricos no se codifican de la misma manera en C y en Java (los bytes más significativos y menos significativos están invertidos).

De esta manera, el entero 100 se codifica:

  • 64 00 00 00 en C;

  • 00 00 00 64 en Java.

Hay que tener en cuenta esta diferencia para la lectura del archivo en Java.

4. La clase Archivo (package herramientasMG.varios)

a. Diagrama de clases

images/24_209.png
  • La clase Archivo hereda de la clase RandomAccessFile, lo que permite utilizar todos los métodos.

  • Facilita el uso de archivos binarios formados por registros de tamaño fijo, creados en C. Las cadenas...