UnidadFlujos y Archivos
-
Upload
jairecko-stylee -
Category
Documents
-
view
24 -
download
0
Transcript of 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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.)