unidadflujos y archivos

22
VIII. Flujos y archivos. “Creo fervientemente en la suerte, y me he dado cuenta que entre más me preparo y estudio, más suerte tengo” Todos los datos fluyen a través de una computadora desde una entrada hacia una salida. La noción genérica de una fuente de entrada puede representar muchos tipos de entrada distintos: desde un archivo de disco, un teclado o un conector (socket) de red. Estas abstracciones son una manera limpia de tratar la Entrada/Salida (E/S) sin necesitar que todo el código comprenda la diferencia entre un teclado y una red. Java llama flujo a esta abstracción y la implementa con varias clases del paquete java.io. El flujo de E/S representa todos los orígenes y destinos de los datos detrás de una interfaz uniforme. Este flujo de datos se denomina también stream. Hay un flujo de entrada (input stream) que manda los datos desde el exterior (normalmente el teclado) de la computadora, y un flujo de salida (output stream) que dirige los datos hacia los dispositivos de salida (la pantalla o un archivo). Estas dos clases abstractas son las que todos los objetos deberían referenciar cuando tratan la E/S en general. En el lenguaje Java los flujos de datos se describen mediante clases que forman jerarquías según sea el tipo de dato char Unicode de 16 bits o byte de 8 bits. A su vez, las clases se agrupan en jerarquías según sea su función de lectura o de escritura. La característica de internacionalización del lenguaje Java es la razón por la que existe una jerarquía separada de clases para la lectura y escritura de caracteres. Todas estas clases se encuentran en el paquete java.io, por lo que al principio del código fuente tendremos que escribir la sentencia import java.io.*; 34

Upload: jairecko-stylee

Post on 02-Aug-2015

24 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: UnidadFlujos y Archivos

VIII. Flujos y archivos. “Creo fervientemente en la suerte, y

me he dado cuenta que entre más me

preparo y estudio, más suerte tengo”

Todos los datos fluyen a través de una computadora desde una

entrada hacia una salida. La noción genérica de una fuente de entrada puede

representar muchos tipos de entrada distintos: desde un archivo de disco, un

teclado o un conector (socket) de red. Estas abstracciones son una manera

limpia de tratar la Entrada/Salida (E/S) sin necesitar que todo el código

comprenda la diferencia entre un teclado y una red.

Java llama flujo a esta abstracción y la implementa con varias clases

del paquete java.io. El flujo de E/S representa todos los orígenes y destinos

de los datos detrás de una interfaz uniforme. Este flujo de datos se denomina

también stream. Hay un flujo de entrada (input stream) que manda los

datos desde el exterior (normalmente el teclado) de la computadora, y un

flujo de salida (output stream) que dirige los datos hacia los dispositivos

de salida (la pantalla o un archivo). Estas dos clases abstractas son las que

todos los objetos deberían referenciar cuando tratan la E/S en general.

En el lenguaje Java los flujos de datos se describen mediante clases

que forman jerarquías según sea el tipo de dato char Unicode de 16 bits

o byte de 8 bits. A su vez, las clases se agrupan en jerarquías según sea su

función de lectura o de escritura. La característica de internacionalización del

lenguaje Java es la razón por la que existe una jerarquía separada de clases

para la lectura y escritura de caracteres.

Todas estas clases se encuentran en el paquete java.io, por lo que al

principio del código fuente tendremos que escribir la sentencia

import java.io.*;

34

Page 2: UnidadFlujos y Archivos

Reader y Writer son las clases bases de la jerarquía para los flujos

de caracteres. Para leer o escribir datos binarios tales como imágenes o

sonidos, se emplea otra jerarquía de clases cuyas clases base son

InputStream y OutputStream.

Rodríguez León menciona que debemos considerar lo siguiente de los

flujos:

• Todos los lenguajes de programación tienen alguna forma de

interactuar con los sistemas de archivos locales; Java no es una

excepción.

• Cuando se desarrollan applets para utilizar en red, hay que tener en

cuenta que la entrada/salida directa a archivo es una violación de

seguridad de acceso. Muchos usuarios configurarán sus navegadores

para permitir el acceso al sistema de archivos, pero otros no.

• Por otro lado, si se está desarrollando una aplicación Java para uso

interno, probablemente será necesario el acceso directo a archivos.

8.1 La clase File.

Antes de realizar acciones sobre un archivo, necesitamos un poco de

información sobre ese archivo. La clase File proporciona muchas utilidades

relacionadas con archivos o directorios en el sistema de archivos de la

plataforma especifica. Mediante esta clase pueden abstraerse las

particularidades de cada sistema de archivos y proporcionar los métodos

necesarios para obtener información sobre los mismos.

Un File es el único objeto del paquete de E/S que referencia a un

archivo de disco real. La clase File no especifica cómo se recupera o

35

Page 3: UnidadFlujos y Archivos

almacena la información en los archivos; sólo describe las propiedades de un

objeto archivo Los objetos archivo se pueden crear utilizando uno de los tres

constructores disponibles (Tabla 8.1). El ejemplo siguiente crea tres archivo:

f1, f2 y f3. El primer objeto File se construye utilizando un trayecto de

directorio como único argumento. El segundo se crea utilizando dos

argumentos, el trayecto y el nombre de archivo. El tercero se crea utilizando

el trayecto de archivo asignado a f1 y un nombre de archivo; f3 refiere al

mismo archivo que f2.

Tabla 8.1. La clase File tiene tres constructores File(String path); File(String path, String name); File(File dir, String name); File f1 = new File("/"); File f2 = new File("/","datos.dat"); File f3 = new File(f1, " datos.dat");

El parámetro path indica el camino hacia el directorio donde se

encuentra el archivo, y name indica el nombre del archivo. Los métodos más

importantes (Tabla 8.2) que describe esta clase son los siguientes:

Tabla 8.2. Métodos de clase File.

Método Uso boolean canRead() True si se puede leer boolean canWrite() True si se puede

escribir int compareTo(File pathname) Compara dos nombres de

trayectoria lexicográficamente.

boolean createNewFile() Crea un nuevo archivo, vacío, asociado a File si y sólo si no existe un archivo con dicho nombre.

36

Page 4: UnidadFlujos y Archivos

Tabla 8.2. Métodos de clase File. Método Uso

boolean delete() True si se puede borrar Void deleteOnExit() Indica a la máquina

virtual que el archivo o directorio correspondiente debe ser borrado cuando la máquina virtual finalice.

boolean exists() True si existe el archivo o directorio.

String getAbsolutePath() Obtiene el path absoluto

String getCanonicalPath() Path canónico String getName() Obtiene el nombre del

archivo o directorio. String getParent() Obtiene el path del

directorio padre. String getPath() Obtiene el path del

archivo. boolean isAbsolute() True si el path es

absoluto. boolean isFile() True si es archivo boolean isDirectory() True si es directorio long lastModified() Devuelve el momento de

la última modificación. long length() Devuelve el tamaño en

bytes del archivo. String[] list() Devuelve los archivos

de un directorio. String[] list(FilenameFilter filter) Igual que el anterior

pero con filtro boolean mkdir() Crea el directorio

indicado. boolean mkdirs() Crea todos los

directorios del path necesarios

boolean renameTo(File destino) Cambia el nombre por el destino

El código 801 ejemplifica los métodos de la clase File descritos en la

tabla 3.4. La única novedad es el uso de la clase Date para trasformar el

resultado del método lastModified de long a un tipo fecha mediante:

Date fUltModif = new Date(archivo.lastModified());

37

Page 5: UnidadFlujos y Archivos

Codigo 801. Implementación de la clase File 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:

import java.io.*; import java.util.*; class Codigo801 { public static void main(String[] args) { File archivo = new File("Codigo801.java"); System.out.println("pathSeparator: "+ archivo.pathSeparator); System.out.println("pathSeparatorChar: " + archivo.pathSeparatorChar); System.out.println("separator: "+ archivo.separator); if(archivo.exists()) { //Ahora obtenemos datos del archivo a analizar... System.out.println("canRead(): "+ archivo.canRead()); System.out.println("canWrite(): "+ archivo.canWrite()); System.out.println("isFile(): "+ archivo.isFile()); System.out.println("isDirectory():" + archivo.isDirectory()); System.out.println("getName(): "+ archivo.getName()); System.out.println("getAbsolutePath(): " + archivo.getAbsolutePath()); System.out.println("getPath(): "+ archivo.getPath()); System.out.println("getParent(): " + archivo.getParent()); System.out.println("isAbsolute(): " + archivo.isAbsolute()); Date fechaUltModif = new Date(archivo.lastModified()); System.out.println("lastModified(): " + archivo.lastModified()); System.out.println("Fecha Ultima Modificación: " + fechaUltModif); System.out.println("length():"+archivo.length()+ "bytes"); System.out.println("length(): " + MisNumeros.dosDigitos(archivo.length()/1024.0) + "Kbytes"); } else { System.out.println("No existe");} try {//espera la pulsación de una tecla y luego RETORNO System.out.print("Pulsa una tecla para continuar"); System.in.read(); }catch (Exception e) { } }//main }//Codigo801

38

Page 6: UnidadFlujos y Archivos

8.2. Operaciones básicas en archivos secuenciales

Cuando hablamos de archivos, habitualmente se utilizan cuatro

términos: campo, registro, archivo y base de datos. Se puede decir que estos

términos forman una estructura de datos agrupados y relacionados de alguna

manera en particular donde uno contiene al otro y que nos facilitan la manera

de almacenarlos y recuperarlos.

a) Un campo es el elemento de datos básico, como ejemplo: un campo

individual contiene un valor único, como el apellido de un empleado,

una fecha o un valor leído por un sensor. Lo más importante de un

campo es su longitud (que puede ser fija o variable) y el tipo de datos

que contenga (ya sea una cadena ASCII o un dígito decimal).

b) Un registro (que se implementa como class en Java) es un conjunto

de campos relacionados que pueden tratarse como una unidad por

algunos programas de aplicación. Por ejemplo: un registro de nombre

“empleado” contendría campos tales como nombre, RFC, fecha de

contratación, etc. Un registro puede ser de longitud variable en el caso

de que el número de campos pueda variar, esto dependerá de su

diseño.

c) Un Archivo es un conjunto de registros similares. Los usuarios y las

aplicaciones se refieren a él por un nombre que es único y puede

crearse y borrarse. Las restricciones al control de acceso suelen

aplicarse a los archivos. Es decir en un sistema compartido, el acceso

de los usuarios y los programas se garantiza o deniega a archivos

completos, en otros casos se aplica a los registros e incluso a los

campos.

39

Page 7: UnidadFlujos y Archivos

d) Una Base de datos es un conjunto de datos relacionados. El aspecto

fundamental es que está diseñada para ser usada por varias

aplicaciones diferentes. Puede contener toda la información relativa a

una organización o proyecto.

La forma más sencilla de almacenar un conjunto de registros en un

archivo es mediante la organización secuencial. En este tipo de archivos, los

registros son escritos consecutivamente cuando el archivo es creado, por lo

tanto, deben se acceden de ese modo cuando se consultan.

La característica más importante de esta técnica de organización de

archivos es que solo permite el acceso secuencial, es decir, para acceder al

registro k, se deben recorrer los k-1 registros anteriores.

La ventaja más importante es la capacidad de acceder al “siguiente”

registro rápidamente, además de que son muy sencillos de usar y de aplicar.

Si la secuencia de acceso a registros en un archivo secuencial es conforme

al ordenamiento físico de los mismos, entonces los tiempos de acceso serán

muy buenos, sin embargo, si el acceso no esta basado en el orden físico de

los registros, entonces la eficiencia del programa puede ser terrible dando

lugar a tiempos de acceso muy altos, provocando una desventaja.

• Creación de un archivo de acceso secuencial.

La clase DataOutputStream es útil para escribir datos del tipo primitivo

de Java en forma portable1. Esta clase tiene un sólo constructor que toma un

objeto de la clase OutputStream o sus derivadas como parámetro. El papel

del objeto DataOutputStrea es proporcionar acceso de alto nivel a un archivo

convirtiendo los valores primitivos de Java en una secuencia de bytes, que se

1 Almacenar datos de manera independiente de la plataforma (o para mandarlos por una red entre computadoras muy distintas).

40

Page 8: UnidadFlujos y Archivos

escriben al archivo utilizando un objeto de tipo FileOutputStream. A

continuación se crea un flujo denominado flujoSalidaDatos. (Tabla 8.3)

Tabla 8.3. Archivo de salida secuencial con DataOutputStream. File Salida = new File("Datos.dat"); FileOutputStream flujoSalida = new FileOutputStream(Salida); DataOutputStream flujoSalidaDatos = DataOutputStream(flujoSalida);

El código mostrado en la tabla 3.5 se puede simplificar en una sola

línea (Tabla 8.4).

Tabla 8.4. Archivo de salida secuencial con DataOutputStream simplificado. DataOutputStream flujoSalidaDatos =new DataOutputStream(new FileOutputStream("Datos.dat"));

Los métodos de la clase DataOutputStream se presentan en la tabla

8.5

Tabla 8.5. Métodos de la clase DataOutputStream. Método Descripción

void close() Cerrar el flujo void flush() Lleva los datos desde el buffer de

memoria directamente al archivo de salida

int size() Tamaño del registro.

Void writeBoolean(boolean v)

Escribe un dato boleano

void writeByte(int v) Escribe un byte void writeBytes(String s) Descompone la cadena de texto en

bytes individuales (obtiene su código ASCII) y los escribe en el flujo de salida. Si la cadena consta de n letras, escribe n bytes, sin añadir ningún delimitador ni de principio ni de fin de cadena

void writeChar(int v) Escribe un entero como char writeChars(String s) Descompone la cadena de texto en

chars individuales (obtiene su código

41

Page 9: UnidadFlujos y Archivos

Tabla 8.5. Métodos de la clase DataOutputStream. Unicode) y los escribe en el flujo de salida. Si la cadena consta de n letras, escribe n chars, sin añadir ningún delimitador ni de principio ni de fin de cadena.

void writeDouble(double v) Escribe un double

void writeFloat(float v) Escribe un flotante void writeInt(int v) Escribe un entero void writeLong(long v) Escribe un entero largo

void writeShort(int v) Escribe un entero corto

void writeUTF(String str) Escribe la cadena en un formato conocido como UTF-8. Este formato incluye información sobre la longitud exacta de la cadena. Este método nos permite recuperar la cadena con facilidad.

Ejemplo: Suponga que usted es el dueño de una ferretería y necesita

llevar un inventario que le pueda decir cuáles son las distintas herramientas

que tiene, cuántas tiene de cada una y su costo desarrolle un archivo

secuencial para almacenar la información de la Tabla 8.6. El código 803a

resuelve este problema.

Tabla 8.6. Datos de prueba del archivo ferreteria.dat

Código Herramienta Cantidad Costo 1 Lijadora eléctrica 18 400.00 2 Martillo 128 90.45 3 Sierra caladora 16 155.20 4 Pulidora de césped 10 928.70 5 Sierra eléctrica 8 1234.25 6 Destornillador 236 53.40 7 Mazo 32 234.25 8 Llave española 65 70.15

La línea 1 del código 803a importa la clase java.io.* necesaria

para acceder a las clases para acceder a los archivos. A la declaración del

42

Page 10: UnidadFlujos y Archivos

main se le agrego una declaración de excepción de entrada y salida (Línea

4). En las líneas 6 - 8 se crea el flujo de salida de datos. Para llevar los datos

del teclado al flujo se usa la clase Datos que permite capturar tanto datos

como cadenas directamente del teclado (Líneas 15, 17 y 19). En las líneas

22-24 se llevan los datos al buffer del flujo, mientras que en la línea 26 los

datos son pasados del buffer al medio de almacenamiento. La instrucción

close cierra el flujo de salida (Línea 30).

Código 803a. Escribir un archivo mediante DataOutput. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

import java.io.*; class Codigo803a { public static void main( String[] args ) throws IOException { /*Se crea el flujo de salida*/ DataOutputStream flujoSalidaDatos = new DataOutputStream( new FileOutputStream("ferreteria.dat")); String articulo = " "; int cantidad; float costo; /* Se inicia un ciclo hasta que se introduce una línea en blanco en articulo*/ while(articulo.length() != 0) { articulo = Datos.Cadena("Articulo"); if(articulo.length() != 0){ cantidad = Datos. Entero("Cuantos " + articulo + ": "); costo = Datos.LeerFlotante("Costo unitario de " + articulo + ": "); /*Se escriben los datos al flujo */ flujoSalidaDatos.writeUTF(articulo); flujoSalidaDatos.writeInt(cantidad); flujoSalidaDatos.writeFloat(costo); /*Datos del buffer se bajan al medio*/ flujoSalidaDatos.flush(); }//if } //while /* Se cierra el flujo*/ flujoSalidaDatos.close(); }//main }//Codigo803

• Leer un archivo de acceso secuencial

43

Page 11: UnidadFlujos y Archivos

Los métodos de la clase DataInputStream son expresados en la

tabla 8.7. Estos métodos sirven para leer un archivo secuencial. Una

implementación de estos métodos para leer los datos generados por el

código 803a se encuentran en el código 803b.

Tabla 8.7. Métodos de la clase DataInputStream. Métodos Descripción

int available()

Devuelve el número de bytes que pueden leerse sin que exista bloqueo.

void close() Cierra el flujo

DataInputStream(InputStream in)

Crea un flujo de entrada, utilizando para ello el flujo pasado como parámetro.

void mark(int readlimit)

Define una posición en el flujo de entrada, a la que es posible retornar antes de haber leído un número igual al parámetro readlimit de bytes, mediante el método reset( ).

boolean markSupported( )

Determina si los métodos de mark() y read() son soportados por la implementación particular de un flujo de entrada. Cuando el valor de retorno de éste método es igual a false un llamado al método reset() generaría una IOException.

int read() Devuelve el byte de datos leído, en caso de encontrarse al final del flujo devuelve -1.

int read(byte[] b) Lee datos en un array de bytes. boolean readBoolean() Lee datos en forma boleana

byte readByte() Lectura, desde el flujo, de un byte.

char readChar() Lectura, desde el flujo una cadena

UNICODE. double readDouble()

Lectura, desde el flujo, de un double.

Float readFloat() Lectura, desde el flujo de un flotante

44

Page 12: UnidadFlujos y Archivos

Tabla 8.7. Métodos de la clase DataInputStream. Métodos Descripción

void readFully(byte[] b)

Lee los bytes dados por b.length iniciando en el apuntador del archivo.

int readInt() Lectura, desde el flujo de un entero (32-bit).

String readLine() Lectura, desde el flujo, de una línea de texto. Esto es, se forma una String con todos los caracteres hasta el siguiente retorno de carro.

long readLong() Lectura, desde el flujo de un entero largo (64-bit).

Short readShort() Lectura, desde el flujo de un entero corto (16-bit).

int readUnsignedByte() Lectura, desde el flujo de un entero sin signo de 8bit.

int readUnsignedShort() Lectura, desde el flujo de un entero sin signo de 16bit.

String readUTF()

void reset() Nos devuelve el flujo desde la última posición marcada.

long skip(long n) Avanza una cantidad de bytes específicos, devuelve el número de bytes que se han pasado por alto.

int skipBytes(int n)) Deja pasar n bytes por alto, efectuando un bloqueo hasta que pasen.

Note que en el ciclo de lectura del archivo “ferreteria.dat” se

implemento una excepción del tipo EOFException (línea 23) la cual captura

el fin del archivo a lo cual imprime el número total de artículos en el inventario

(Línea 27) y su costo (Línea 28). El costo se imprime con la configuración

declarada en el entorno del equipo de cómputo donde se ejecute el código

mediante una clase declarada como MisNumeros.

45

Page 13: UnidadFlujos y Archivos

Código 803b. Escribir un archivo mediante DataInput. 1: 2: 3: 4: 5: 6: 7: 8: 9:

10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34:

import java.io.*; class Codigo803b { public static void main( String[] args ) throws IOException { /* Se crea el flujo de entrada */ DataInputStream EntDatos = new DataInputStream( new FileInputStream("ferreteria.dat")); double costo = 0, precio; int nArticulos = 0, n; try { while(true) { /* Se leen los datos del flujo*/ System.out.print(EntDatos.readUTF()+":"); n = EntDatos.readInt(); System.out.print(n + ": "); precio = EntDatos.readFloat(); nArticulos += n; costo += precio * n; System.out.println( MisNumeros.dosDigitos(precio)) n; } //while } catch (EOFException e) { /* Se genera una excepción al encontrar el fin de archivo*/ System.out.println("En inventario hay " + nArticulos + " articulos " + " con un costo de " + MisNumeros.getCurrencyValue(costo)); }/*EOFException*/ /* Se cierra el flujo */ flujoEntradaDatos.close(); }//main }//Codigo803b

8.3 Operaciones básicas en archivos de acceso aleatorio.

Los archivos de acceso aleatorio te permiten almacenar o recuperar

información aleatoriamente, es decir que si deseas guardar o información

sobre el alumno cuyo número de control es 97020016 el apuntador del

archivo se desplazara libremente hasta ese número de control y escribir

sobre ella, no se requiere orden en los datos.

46

Page 14: UnidadFlujos y Archivos

La clase RandomAccessFile nos da las capacidades que buscamos

de lectura y escritura de archivos binarios. En estos archivos hay un índice

que nos dice en qué posición del archivo nos encontramos, y con el que se

puede trabajar para posicionarse en el archivo.

Cuando se escriben los datos sean del tipo que sean en un archivo

aleatorio estos deben ser convertidos a su contraparte en bytes, por motivos

didácticos lo idealizamos de la siguiente manera:

Registro 1

Número Nombre Edad Sexo

Registro 2

Número Nombre Edad Sexo

Registro 3

Número Nombre Edad Sexo

Figura 3.8. Registro

Y así sucesivamente. Se pretende visualizar un archivo de acceso

aleatorio como un grupo de registros, cada registro tiene en este ejemplo 4

cuadros: Número (entero), Nombre (String), Edad (Entero) y Sexo (Char).

El constructor que utilizaremos para este ejemplo es: public RandomAccessFile(String nombre, String modo) ;

Donde "nombre" representa el nombre del archivo y "modo" indica la

forma en la cual abriremos el archivo, ambos son cadenas. El nombre es

libre de elegir si se trata de un archivo nuevo o debe ser consultado en el

caso de un archivo existente (el caso del ejemplo), el nombre se coloca con

su extensión correspondiente.

47

Page 15: UnidadFlujos y Archivos

En cuanto al modo existen cuatro posibilidades: "rw", “rws”, "rwd",

“r”. “rw” indica lectura y escritura (read & write), “rws” permite que el archivo

se abra para lectura y escritura, pero también requiere que cada

actualización del contenido del archivo esté escrita sincrónicamente de

acuerdo con el dispositivo de almacenamiento subyacente, “rwd” . mientras

que “r” indica solo lectura.

La tabla 8.8 muestra algunos métodos de la clase RandomAccessFile:

Tabla 8.8. Métodos de la clase RandomAccessFile Método Descripción

void close() Cierra el archivo de acceso aleatorio y libera todos los recursos del sistema asociados con este archivo

FileChannel getChannel() Proporciona la posibilidad de realizar trasferencias directas de bytes de un FileChannel a otro utilizando al máximo las posibilidades del sistema operativo

FileDescriptor getFD() Devuelve el descriptor del archivo. long getFilePointer() Devuelve la posición actual del puntero

del archivo. long length() Devuelve la longitud del archivo. boolean readBoolean() Lee un byte y devuelve false si vale 0 o

true sino. byte readByte() Lee y devuelve un byte. char readChar() Lee y devuelve un caracter. double readDouble() Lee 8 bytes, y devuelve un double. float readFloat() Lee 4 bytes, y devuelve un flotante. void readFully(byte[] b) Lee bytes del archivo y los almacena en

un vector b. int readInt() Lee 4 bytes, y devuelve un int. long readLong() Lee 8 bytes, y devuelve un long. short readShort() Lee 2 bytes, y devuelve un short int readUnsignedByte() Lee 1 byte, y devuelve un valor de 0 a

255. int readUnsignedShort() Lee 2 bytes, y devuelve un valor de 0 a

65535

48

Page 16: UnidadFlujos y Archivos

Tabla 8.8. Métodos de la clase RandomAccessFile Método Descripción String readUTF() Lee una cadena codificada con el

formato UTF-8. void seek(long pos) Coloca el puntero del archivo en la

posición indicada por “pos”. Un archivo siempre empieza en la posición 0.

void

setLength(long newLength)

Establece a newLength el tamaño de este archivo.

int skipBytes(int n) Intenta saltar n bytes desde la posición actual.

void writeBoolean(boolean v) Escribe el boolean v como un byte. void writeChar(int v) Escribe v como 1 byte. void writeDouble(double v) Convierte v a double y le escribe como

8 bytes. void writeFloat(float v) Convierte v a flotante y lo escribe en el

flujo en 4 bytes. void writeInt(int v) Escribe v como 4 bytes. void writeLong(long v) Escribe v como 8 bytes. void writeShort(int v) Escribe v como 2 bytes void writeUTF(String str) Escribe la cadena v utilizando la

codificación UTF-8.

Ejemplo: A continuación se presenta en el código 804, la implentación

de un archivo de acceso aleatorio para guardar ciertos datos como número

de control, nombre del alumno, correo electrónico y teléfono. Para este

archivo se implementaran las operaciones de Alta (agregar), Buscar, Editar y

Mostrar. Solo resta incluir el borrado para tener un ABC, debemos hacer

hincapié que el borrado en archivos aleatorios se implementa lógicamente,

en la unidad cuatro presentaremos un proceso que implementa el borrado

físico.

El ingreso de datos desde teclado, se logra mediante una clase

llamada “Datos”, diseñada de tal forma que los valores String tengan un

tamaño específico (Líneas 9 a 12). Es necesario que las cadenas tengan un

49

Page 17: UnidadFlujos y Archivos

tamaño específico para que la edición sea factible, por lo tanto si la cadena

es menor a la deseada se rellena de blancos por la derecha. Si la cadena es

mayor se regresa la subcadena del tamaño especificado (línea 14).

Código 803c. Método de captura por teclado de cadenas. 1: 2: 3: 4: 5: 6: 7: 8: 9:

10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:

public static String getCadena(String mens, int n){ String sdato, S = ""; BufferedReader bufer; try { System.out.print(mens + ": "); Buffer = new BufferedReader(new InputStreamReader(System.in)); sdato = bufer.readLine(); if((sdato.length() > 0) && ( sdato.length() < n)) { for(int i = sdato.length(); i < n;i++) sdato += " ";} else { if(sdato.length() > n) sdato = sdato.substring(0,n); } return sdato; } catch(IOException e){ System.out.println("No es una cadena..."); return null; } }//getCadena

Las líneas 8 al 20 del código abren el archivo de datos si ocurre algún

valor regresan un número mayor que cero y termina la ejecución. Para

escribir directamente al archivo se implemento el método Escribe (líneas

22-34) de ocurrir un error regresa un false. El método Agregar (líneas 44 –

64) anexa datos al final archivo (línea 67) tiene como restricción que el

número de control sea mayor que cero.

Código 804. Archivo de acceso aleatorio. 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:

import java.lang.*; import java.io.*; import java.util.*; public class Codigo804 { private static RandomAccessFile archivo; public static int Abrir(){ try { archivo = new

50

Page 18: UnidadFlujos y Archivos

Código 804. Archivo de acceso aleatorio. 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62:

RandomAccessFile("Codigo804.dat", "rw"); return 0; } catch(FileNotFoundException e) { System.out.println("No existe archivo"); return 1; } catch(IOException e) { System.out.println("IO Exception"); return 1; } } private static boolean Escribe(int numero, String nombre, String email, long tel) { try { archivo.writeInt(numero); archivo.writeUTF(nombre); archivo.writeUTF(email); archivo.writeLong(tel); return true; } catch(IOException e) { System.out.println("IO Exception"); return false; } } //Escribe Archivo private static void Imprime(int n, String nomb, String em, long tel) { System.out.println(n); System.out.println(nomb); System.out.println(em); System.out.println(tel); } //Imprime private static void Agregar() { try { /*Se agrega al final del archivo*/ archivo.seek(archivo.length()); /*Numero de control del alumno*/ int numeroControl = Datos.getEntero("Número de control"); if(numeroControl > 0){ String nombreAlumno = Datos.getCadena("Nombre del alumno", 30); String email = Datos.getCadena("Correo electrónico", 40); long telefono = Datos.getLargo("Número de teléfono"); Escribe(numeroControl, nombreAlumno, email, telefono); } } catch(IOException e) { System.out.println("IO Exception");

51

Page 19: UnidadFlujos y Archivos

Código 804. Archivo de acceso aleatorio. 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99:

100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114:

} }//Agregar private static void Buscar() throws IOException { int numeroControl = 0, nc = 0; long telefono = 0; String nombreAlumno = "", email = ""; try { numeroControl = Datos.getEntero("Número de Control"); if(numeroControl > 0) { archivo.seek(0); while(numeroControl != nc){ nc = archivo.readInt(); nombreAlumno = archivo.readUTF(); email = archivo.readUTF(); telefono = archivo.readLong(); archivo.seek(archivo.getFilePointer()); }//while Imprime(nc, nombreAlumno, email, telefono); } } catch (EOFException e) { /* Se genera una excepción al encontrar el fin de archivo*/ System.out.println("No se encontró el número de control: " + numeroControl); } }//Mostrar private static void Mostrar() throws IOException { try { archivo.seek(0); while(true){ Imprime(archivo.readInt(), archivo.readUTF(), archivo.readUTF(), archivo.readLong()); System.out.println(); archivo.seek(archivo.getFilePointer()); }//while } catch (EOFException e) { /* Se genera una excepción al encontrar el fin de archivo*/ System.out.println("Fin de archivo"); } }//Mostrar private static void Editar() throws IOException { int numeroControl = 0, nc = 0; long posicion, telefono = 0, tel; String S, nombreAlumno = "", email = ""; try { numeroControl =

52

Page 20: UnidadFlujos y Archivos

Código 804. Archivo de acceso aleatorio. 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166:

Datos.getEntero("Número de Control"); if(numeroControl > 0) { archivo.seek(0); do { posicion = archivo.getFilePointer(); archivo.seek(posicion); nc = archivo.readInt(); nombreAlumno = archivo.readUTF(); email = archivo.readUTF(); telefono = archivo.readLong(); }while(numeroControl != nc); if(numeroControl == nc) { archivo.seek(posicion); nc = archivo.readInt(); nombreAlumno = archivo.readUTF(); email = archivo.readUTF(); telefono = archivo.readLong(); Imprime(nc, nombreAlumno, email, telefono); archivo.seek(posicion); S = Datos.getCadena("Nombre ", 30); nombreAlumno = (S.length() > 0)? S: nombreAlumno; S = Datos.getCadena("Correo", 40); email = (S.length() > 0)? S: email; tel = Datos.getLargo("telefono"); telefono = (tel > 0) ? tel: telefono; Escribe(numeroControl, nombreAlumno, email, telefono); } } } catch (EOFException e) { /* Se genera una excepcion al encontrar el fin de archivo*/ System.out.println("No se encontró el número de control: " + numeroControl); } }//Editar public static void main(String[] args) throws IOException { int opcion = 5; if(Abrir()== 0) do { System.out.println("\n\t1)Agregar\n\t2)Buscar\n\t 3)Editar\n\t4)Mostrar\n\t5)Salir"); opcion = Datos.getEntero("Opción"); switch(opcion){ case 1: Agregar(); break; case 2: Buscar(); break; case 3: Editar(); break; case 4: Mostrar(); break;

53

Page 21: UnidadFlujos y Archivos

Código 804. Archivo de acceso aleatorio. 167: 168: 169: 170: 171: 172:

} //switch } while(opcion != 5); archivo.close(); System.out.println("Bye"); }//main }// Codigo804

54

Page 22: UnidadFlujos y Archivos

Nombre de archivo: Unidad08.doc Directorio: C:\Documents and Settings\epacheco\Mis

documentos\UMLJAVA\Java Plantilla: C:\Documents and Settings\epacheco\Datos de

programa\Microsoft\Plantillas\Normal.dot Título: VIII Asunto: Autor: Jose Evaristo Pacheco Velasco Palabras clave: Comentarios: Fecha de creación: 17/10/2005 14:16:00 Cambio número: 3 Guardado el: 17/10/2005 14:38:00 Guardado por: Evaristo Pacheco Tiempo de edición: 9 minutos Impreso el: 17/10/2005 14:48:00 Última impresión completa Número de páginas: 21 Número de palabras: 4,954 (aprox.) Número de caracteres: 27,299 (aprox.)