Entrada y salida de archivos - Computación -...

29
Entrada y salida de archivos H. Tejeda Abril 2016 ´ Indice 1. Introducci´ on 1 2. Clases Path y Files 3 3. Organizaci´ on de archivos, flujos, y b´ ufers de datos 10 4. Clases entrada/salida 12 5. Archivos secuenciales de datos 17 6. Archivos de acceso aleatorio 20 7. Escritura de registros en archivos de acceso aleatorio 23 8. Lectura de registros en archivos de acceso aleatorio 26 Se da una introducci´ on de como se guarda la informaci´ on en un sistema de c´ omputo, y los medios que este tiene para llevarlo a cabo. Despu´ es se comentan algunas clases que pueden ser usadas para realizar algunas tareas con archivos. 1. Introducci´ on Los elementos de datos pueden ser guardados en dos tipos de dispositivos de almacenamiento en un sistema de c´ omputo: Almacenamiento vol´ atil es temporal; valores que son volatiles, como los que son guardados en variables, se pierden cuando la computadora deja de ser energizada. RAM (random 1

Transcript of Entrada y salida de archivos - Computación -...

Page 1: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

Entrada y salida de archivos

H. Tejeda

Abril 2016

Indice

1. Introduccion 1

2. Clases Path y Files 3

3. Organizacion de archivos, flujos, y bufers de datos 10

4. Clases entrada/salida 12

5. Archivos secuenciales de datos 17

6. Archivos de acceso aleatorio 20

7. Escritura de registros en archivos de acceso aleatorio 23

8. Lectura de registros en archivos de acceso aleatorio 26

Se da una introduccion de como se guarda la informacion en un sistema de computo, y los mediosque este tiene para llevarlo a cabo. Despues se comentan algunas clases que pueden ser usadas pararealizar algunas tareas con archivos.

1. Introduccion

Los elementos de datos pueden ser guardados en dos tipos de dispositivos de almacenamiento enun sistema de computo:

Almacenamiento volatil es temporal; valores que son volatiles, como los que son guardadosen variables, se pierden cuando la computadora deja de ser energizada. RAM (random

1

Page 2: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

access memory) es el almacenamiento temporal dentro de una computadora. Tambien sele conoce como memoria de almacenamiento volatil.

Almacenamiento no volatil es almacenamiento permanente; no se pierde al desenergizarla computadora. Cuando se escribe un programa Java y se guarda en el disco, se esta usandoalmacenamiento permanente.

Un archivo de computadora es una coleccion de datos guardados en un dispositivo no volatil.El archivo existe en dispositivos de almacenamiento permanente, tales como discos duros,discos ZIP, memorias USB, carretes de cinta magnetica, discos compactos, etc.

Se pueden clasificar los archivos por la forma como estos guardan los datos:

Archivos de texto contienen datos que pueden ser leıdos por un editor de texto porque losdatos han sido codificados usando un esquema como ASCII o Unicode. Algunos archivos detexto son archivos de datos como uno que tenga una nomina con numero de empleado,nombre y salario; otros archivos son archivos de programa o archivos de aplicacion queguardan instrucciones de software.

Archivos binarios contienen datos que no han sido codificados como texto. Ejemplos deestos archivos son imagenes, musica, archivos de programa compilados.

Los archivos tienen muchas caracterısticas comunes—cada archivo tiene un tamano que indica elespacio que ocupa en una seccion del disco u otro dispositivo de almacenamiento, y cada archivotiene un nombre y un tiempo especıfico de creacion.

Cuando se guarda un archivo permanente, este se puede poner en el directorio principal o raız deldispositivo de almacenamiento. Para una mejor organizacion los sistemas de computo organizansus archivos en carpetas o directorios. Se pueden crear directorios dentro de otros para formaruna jerarquıa. La jerarquıa de directorios en el cual reside un archivo es su camino. Por ejemplo, elsiguiente es el camino completo para un archivo de Linux llamado nano, el cual esta en el directoriobin, y este a su vez dentro de usr:

/usr/bin/nano

En el sistema operativo de las ventanas, la diagonal invertida (\) es el delimitador de camino.En los sistemas operativos UNIX o variantes se usa una diagonal (/) como delimitador.

Cuando se trabaja con archivos en una aplicacion, se realizan con estos las siguientes tareas:

Determinar si un camino o archivo existe.

Abrir un archivo.

Escribir a un archivo.

Leer desde un archivo.

2

Page 3: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

Cerrar un archivo.

Borrar un archivo.

Java da clases incorporadas que contienen metodos para realizar estas tareas.

2. Clases Path y Files

Se usa la clase Path para crear objetos que contengan informacion acerca de archivos y directorios,tal como su lugar, tamano, fecha de creacion, y si existen. Se usa la clase Files para realizaroperaciones en archivos y directorios, como borrar, conocer sus atributos, creacion de flujos deentrada y salida.

Para usar las clases Path y Files se puede usar la siguiente sentencia al inicio del programa:

import java.nio.file.*;

El paquete nio (new input/output) agrupa las clases desarrolladas bastante despues de las primerasversiones de Java. Las clases Path y Files son nuevas en Java 7; reemplazan la funcionalidad dela clase File usada en versiones mas viejas de Java.

Crear un camino

Para crear un camino, primero se debe determinar el sistema de archivos por defecto en la compu-tadora anfitrion usando una sentencia como la siguiente:

FileSystem fs = FileSystems.getDefault();

La sentencia crea un objeto FileSystem usando el metodo getDefault() de la clase FileSystems,se estan usando dos clases diferentes. La clase FileSystem se usa para declarar el objeto y FileSys-

tems es una clase que contiene metodos de fabrica que ayudan en la creacion del objeto.

Despues de crear un objeto FileSystem, se puede definir una Path (ruta) usando el metodogetPath():

Path ruta = fs.getPath("/usr/bin/nano");

Si se tiene que usar la diagonal invertida (backslash) para construir la ruta esta debera escaparseen la sentencia donde se use. Otra forma de hacerlo serıa concatenar cadenas con los nombres dedirectorios y archivos e intercalar llamadas al metodo de instancia getSeparator() con un objetoFileSystem:

Path rutaArchivo = fs.getPath(fs.getSeparator()+"usr"+fs.getSeparator()+

"bin"+fs.getSeparator()+nano);

3

Page 4: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

Otra forma para crear un Path es usar la clase Paths. La clase Paths es una clase de ayuda queevita crear un objeto FileSystem. El metodo get() de Paths llama al metodo getPath() delsistema de archivos. Se puede crear un objeto Path usando la siguiente sentencia:

Path rutaArchivo = Paths.get("/usr/bin/nano");

Cuando una aplicacion declara un camino y se quiere usar la aplicacion con un archivo diferente,se podrıa cambiar solo el String pasado al metodo de instanciacion.

Cada Path es absoluto o relativo. Un camino absoluto es un camino completo; no necesita otrainformacion para localizar un archivo. Un camino relativo depende del directorio de trabajo parala localizacion. Una ruta simple como ArchivoEjemplo.txt es relativo. Cuando se trabaja con uncamino que contiene solo una archivo, se asume que el archivo esta en el mismo directorio. De igualforma cuando se refiere a un camino relativo como datos/ArchivoEjemplo.txt, se asume que eldirectorio datos es un subdirectorio del directorio actual, y ArchivoEjemplo.txt se asume queesta dentro de ese folder.

Recuperacion de informacion acerca de un camino

En el cuadro 1 se resumen varios metodos Path utiles. El metodo toString() de la clase Object esanulado; haciendo que devuelva un String de la representacion de Path. El metodo getFileName()

devuelve la ultima sentencia en una lista de caminos; la mayorıa de las veces es un archivo, peropodrıa ser el nommbre de una carpeta.

Metodo Descripcion

String toString() Devuelve la representacion String del Path.Path getFileName() Regresa el archivo o directorio dado por este Path; este es el

ultimo elemento en la secuencia de elementos nombre.int getNameCount() Devuelve la cantidad de elementos nombre en el Path.Path getName(int) Regresa el nombre en la posicion del Path indicado por el parame-

tro entero.

Cuadro 1: Algunos metodos de la clase Path

Un elemento de Path es accedido por un ındice. El elemento de la cima en la estructura directorioesta localizado en el ındice cero; el elemento mas bajo en la estructura es accedido por el metodogetName() y tiene un ındice que es uno menos que la cantidad de elementos en la lista. Para saberla cantidad de elementos en la lista usar el metodo getNameCount() y para recuperar el nombreen la posicion indicada por el argumento usar getNameCount.

La aplicacion DemoPath, codigo 1, que crea un Path y usa algunos de los metodos del cuadro 1.

4

Page 5: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

1 import java . n io . f i l e . ∗ ;2 public class DemoPath {3 public stat ic void main ( St r ing [ ] a rgs ) {4 Path caminoArch = Paths . get ( ”/ e t c /passwd” ) ;5 int contador = caminoArch . getNameCount ( ) ;6 System . out . p r i n t l n ( ”El camino es ” + caminoArch . t oS t r i ng ( ) ) ;7 System . out . p r i n t l n ( ”El nombre de l a rch ivo es ” +8 caminoArch . getName ( contador −1)) ;9 System . out . p r i n t l n ( ”Hay ” + contador +

10 ” elementos en e l camino de l a rch ivo ” ) ;11 for ( int x = 0 ; x < contador ; ++x )12 System . out . p r i n t l n ( ”\ tElemento ” + x + ” es ” +13 caminoArch . getName ( x ) ) ;14 }15 }

Codigo 1: La clase DemoPath.

Cuando se ejecuta el programa DemoPath con el archivo /etc/passwd se obtiene la siguiente salida:

$ java DemoPath

El camino es /etc/passwd

El nombre del archivo es passwd

Hay 2 elementos en el camino del archivo

Elemento 0 es etc

Elemento 1 es passwd

Conversion de un camino relativo a absoluto

El metodo toAbsolutePath() convierte un camino relativo a uno absoluto. La aplicacion DemoPath2,codigo 2, muestra una aplicacion que pide al usuario un nombre de archivo y, si se puede, lo conviertea un camino absoluto.

1 import java . u t i l . Scanner ;2 import java . n io . f i l e . ∗ ;3 public class DemoPath2 {4 public stat ic void main ( St r ing [ ] a rgs ) {5 St r ing nombre ;6 Scanner t e c l ado = new Scanner ( System . in ) ;7 System . out . p r i n t ( ” I n g r e s a r e l nombre de un arch ivo >> ” ) ;8 nombre = tec l ado . nextLine ( ) ;9 Path caminoDado = Paths . get ( nombre ) ;

10 Path caminoCompleto = caminoDado . toAbsolutePath ( ) ;11 System . out . p r i n t l n ( ”El camino completo es ” +12 caminoCompleto . t oS t r i ng ( ) ) ;13 }14 }

Codigo 2: La clase DemoPath2.

Cuando se ejecuta la aplicacion DemoPath2, el nombre ingresado podrıa representar un camino

5

Page 6: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

relativo. Si la entrada representa un camino absoluto, no se modifica la entrada, caso contrario elprograma crea un camino absoluto asignando al archivo el directorio actual. Enseguida se muestrauna ejecucion del programa.

$ java DemoPath2

Ingresar el nombre de un archivo >> DemoPath.java

El camino completo es /home/fismat/DemoPath.java

Revisar accesibilidad de un archivo

Para saber si un archivo existe y que el programa pueda accederlo como se requiera, se puede usar elmetodo checkAccess(). La siguiente sentencia import permite el acceso a constantes que puedenser usadas como argumentos al metodo:

import static java.nio.file.AccessMode.*;

Mediante un objeto Path, referido por archivo, la sintaxis para usar el metodo checkAccess() esla siguiente:

archivo.getFileSystem().provider().checkAccess();

Cualquiera de los siguientes argumentos puede ser usado con el metodo checkAccess():

Sin argumentos—Revisa que el archivo exista; como una alternativa, se puede sustituir elmetodo Files.exists() y pasarle un argumento Path.

READ—Revisa que el archivo exista y que tenga permiso de lectura.

WRITE—Revisa que el archivo exista y que tenga permiso de escritura.

EXECUTE—Revisa que el archivo exista y que tenga permiso de ejecucion.

Nota. La caracterıstica static import de Java se logra cuando se pone la palabra reservada

static entre import y el nombre del paquete siendo importado. Esta caracterıstica permite usar

constantes static sin el nombre nombre de su clase. Por ejemplo, si se quita static de la sentencia

import para java.nio.file.AccessMode, se debera referir a la constante READ por su nombre

completo como AccessMode.READ; cuando se usa static, se puede referir a esta solo como READ.

Se pueden usar argumentos multiples con el metodo checkAccess(), separados por comas. Si elarchivo no puede ser accedido como se indica en la llamada del metodo, una IOException eslanzada. El codigo 3 muestra una aplicacion que declara un Path y revisa si el archivo puede serleıdo y ejecutado. En la lınea 3 del codigo 3, se debe importar el paquete java.io.IOException

porque una excepcion podrıa ser instanciada y lanzada.

6

Page 7: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

1 import java . n io . f i l e . ∗ ;2 import stat ic java . n io . f i l e . AccessMode . ∗ ;3 import java . i o . IOException ;4 public class DemoPath3 {5 public stat ic void main ( St r ing [ ] a rgs ) {6 Path arch ivo = Paths . get ( ”/ e tc /passwd” ) ;7 System . out . p r i n t l n ( ”Path es ” + arch ivo . t oS t r i ng ( ) ) ;8 try {9 arch ivo . getFi l eSystem ( ) . p rov ide r ( ) . checkAccess ( archivo ,READ,EXECUTE) ;

10 System . out . p r i n t l n ( ”El arch ivo puede s e r l e ıdo y e j ecutado ” ) ;11 }12 catch ( IOException e ) {13 System . out . p r i n t l n ( ”El arch ivo no puede s e r usado por l a a p l i c a c i on” ) ;14 }15 }16 }

Codigo 3: La clase DemoPath3.

A continuacion se muestra la salida del codigo 3 al ser ejecutado.

$ java DemoPath3

Path es /etc/passwd

El archivo no puede ser usado por la aplicacion

Nota. Un programa podrıa encontrar a un archivo utilizable, pero luego el archivo podrıa hacerse

no utilizable antes de ser usado en una sentencia siguiente. Este tipo de error es llamado error

TOCTTOU (Time Of Check To Time Of Use).

Borrar un camino

El metodo delete() de la clase Files acepta un parametro Path y borra el ultimo elemento(archivo o directorio) en un camino o lanza una excepcion si falla el borrado. Por ejemplo:

Si se intenta borrar un archivo que no existe, una NoSuchFileException es lanzada.

Un directorio se puede borrar cuando esta vacıo. Si se intenta borrar un directorio que contienearchivos, una DirectoryNotEmptyException es lanzada.

Si se intenta borrar un archivo pero no se tiene permiso, una SecurityException es lanzada.

Otros errores de entrada/salida provocan una IOException.

La aplicacion DemoPath4, codigo 4, muestra un mensaje apropiado en cada uno de los escenariosprecedentes despues de intentar borrar un archivo.

7

Page 8: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

1 import java . n io . f i l e . ∗ ;2 import java . i o . IOException ;3 public class DemoPath4 {4 public stat ic void main ( St r ing [ ] a rgs ) {5 Path caminoArchivo = Paths . get ( ”/ e tc /passwd” ) ;6 try {7 F i l e s . d e l e t e ( caminoArchivo ) ;8 System . out . p r i n t l n ( ”El arch ivo o d i r e c t o r i o e s t a borrado ” ) ;9 }

10 catch ( NoSuchFileException e ) {11 System . out . p r i n t l n ( ”No e x i s t e e l a rch ivo o d i r e c t o r i o ” ) ;12 }13 catch ( DirectoryNotEmptyException e ) {14 System . out . p r i n t l n ( ”El d i r e c t o r i o no e s t a vacıo” ) ;15 }16 catch ( Secur i tyExcept ion e ) {17 System . out . p r i n t l n ( ”No t i e n e permiso para borrar ” ) ;18 }19 catch ( IOException e ) {20 System . out . p r i n t l n ( ” Exception IO” ) ;21 }22 }23 }

Codigo 4: La clase DemoPath4.

El metodo deleteIfExists() de la clase Files tambien puede ser usado para borrar un archivo,pero si el archivo no existe, no se lanza excepcion.

Determinar atributos de archivo

El metodo readAttributes() de la clase Files se puede usar para recuperar informacion util de unarchivo. Se deben dar dos argumentos al metodo, un objeto Path y BasicFileAttributes.class,y devuelve una instancia de la clase BasicFileAttributes. Se podrıa crear una instancia con unasentencia como la siguiente:

BasicFileAttributes atrib =

Files.readAttributes(caminoArchivo, BasicFileAttributes.class);

Despues de crear un objeto BasicFileAttributes, se dispone de un conjunto de metodos pararecuperar informacion del archivo. Como, el metodo size() que da el tamano del archivo en bytes,los metodos creationTime() y lastModifiedTime() que dan fechas del archivo. La aplicacionDemoPath5, codigo 5, usa estos metodos.

8

Page 9: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

1 import java . n io . f i l e . ∗ ;2 import java . n io . f i l e . a t t r i b u t e . ∗ ;3 import java . i o . IOException ;4 public class DemoPath5 {5 public stat ic void main ( St r ing [ ] a rgs ) {6 Path caminoArchivo = Paths . get ( ”/ e tc /passwd” ) ;7 try {8 B a s i c F i l e A t t r i b u t e s a t r i b =9 F i l e s . r eadAtt r ibute s ( caminoArchivo , B a s i c F i l e A t t r i b u t e s . class ) ;

10 System . out . p r i n t l n ( ” Fecha de c r e a c i on : ” + a t r i b . creat ionTime ( ) ) ;

11 System . out . p r i n t l n ( ”U l t ima m o d i f i c a c i on : ” +12 a t r i b . lastModi f iedTime ( ) ) ;13 System . out . p r i n t l n ( ” Tamano : ” +a t r i b . s i z e ()+” bytes ” ) ;14 }15 catch ( IOException e ) {16 System . out . p r i n t l n ( ” Excepci on E/S” ) ;17 }18 }19 }

Codigo 5: La clase DemoPath5.

Los metodos de fecha en el programa DemoPath5 devuelven un objeto FileTime que es convertidoa un String en la llamada al metodo println(). Los objetos FileTime son representados en elsiguiente formato:

aaaa-mm-ddThh:mm:ss

El formato descrito se puede ver en la siguiente salida:

$ java DemoPath5

Fecha de creacion: 2013-10-23T15:16:20Z

Ultima modificacion: 2013-10-23T15:16:20Z

Tama~no: 5253 bytes

Para determinar la relacion de fechas entre dos archivos, se puede usar el metodo compareTo(). Laaplicacion DemoPath6, codigo 6, muestra como se pueden comparar las fechas de creacion de dosarchivos. El metodo compareTo() regresa un valor menor que cero si el primer FileTime esta antesque el argumento de FileTime. Regresara el metodo un valor mayor que cero si el primer FileTimees posterior al del argumento y cero si los valores de FileTime son los mismos.

Nota. Java soporta clases especializadas para atributos de archivos DOS y de Windows, como oculto,

o solo lectura y atributos de archivos POSIX usados en sistemas como UNIX, donde los archivos

tiene dueno y grupo.

9

Page 10: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

1 import java . n io . f i l e . ∗ ;2 import java . n io . f i l e . a t t r i b u t e . ∗ ;3 import java . i o . IOException ;4 public class DemoPath6 {5 public stat ic void main ( St r ing [ ] a rgs ) {6 Path arch1 = Paths . get ( ”/ e t c /passwd” ) ;7 Path arch2 = Paths . get ( ”/ e t c / hos t s ” ) ;8 try {9 B a s i c F i l e A t t r i b u t e s a t t r 1 =

10 F i l e s . r eadAtt r ibute s ( arch1 , B a s i c F i l e A t t r i b u t e s . class ) ;11 B a s i c F i l e A t t r i b u t e s a t t r 2 =12 F i l e s . r eadAtt r ibute s ( arch2 , B a s i c F i l e A t t r i b u t e s . class ) ;13 FileTime time1 = a t t r 1 . creat ionTime ( ) ;14 FileTime time2 = a t t r 2 . creat ionTime ( ) ;15 System . out . p r i n t l n ( ”La fecha de c r e a c i on de arch1 es : ” + time1 ) ;16 System . out . p r i n t l n ( ”La fecha de c r e a c i on de arch2 es : ” + time2 ) ;17 i f ( time1 . compareTo ( time2 ) < 0)18 System . out . p r i n t l n ( ” arch1 fue creado antes que arch2 ” ) ;19 else i f ( time1 . compareTo ( time2 ) > 0)20 System . out . p r i n t l n ( ” arch1 fue creado despues que arch2 ” ) ;21 else22 System . out . p r i n t l n ( ” arch1 y arch2 fueron creados a l mismo tiempo” ) ;23 }24 catch ( IOException e ) {25 System . out . p r i n t l n ( ” Excepci on E/S” ) ;26 }27 }28 }

Codigo 6: La clase DemoPath6.

3. Organizacion de archivos, flujos, y bufers de datos

Se pueden guardar datos en variables dentro de un programa, pero el almacenamiento es temporal.Por otra parte, cuando la aplicacion termina, las variables dejan de existir y los valores de datos sepierden. Las variables son guardadas en la memoria principal o primaria (RAM) de la computadora.Para retener datos por alguna cantidad significativa de tiempo, se deben guardar los datos en undispositivo de almacenamiento permanente, o secundario, como un disco.

La pieza util mas pequena de datos para la mayorıa de los usuarios es el caracter. Un caracterpuede ser cualquier letra, numero, o sımbolos especiales (como signos de puntuacion) que formanlos datos. Los caracteres estan formados con bits (los ceros y los unos que representan los valoreslogicos usados por el sistema de computo), pero a los usuarios no les importa si la representacionde algun caracter es hecha con alguna combinacion de ceros y unos, o con alguna otra. Los usuariosestan interesados con el significado que pueda tener algun caracter, tratandose de alguna letraesta podrıa ser una inicial, algun codigo, etc. Un caracter podrıa ser cualquier grupo de bits y nonecesariamente representar una letra o un numero; por ejemplo, algunos “caracteres” producen unsonido o controlan el monitor. Tambien, los caracteres no son necesariamente creados con una solatecla; por ejemplo, las secuencias escapadas son usadas para crea el caracter ’\n’, el cual iniciauna nueva lınea. En ocasiones, se puede pensar en un caracter como una unidad de informacion

10

Page 11: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

en vez de un dato con una apariencia particular. Por ejemplo, el caracter matematico π y la letragriega pi parecen iguales, pero tienen dos valores Unicode diferentes.

En las organizaciones que usan datos, estas agrupan los caracteres en campos. Un campo es ungrupo de caracteres que tienen algun significado. Los caracteres J, u, a y n podrıan representarun nombre. Otros campos de datos podrıan representar elementos como los apellidos, numero deseguridad social, codigo postal, o salario.

Los campos estan agrupados para formar registros. Un registro es una coleccion de campos quecontienen datos acerca de una entidad. Por ejemplo, el nombre, los apellidos, el numero de seguridadsocial, el codigo postal y el salario representan un registro de una persona. En las clases, vistaspreviamente, como Empleado o Estudiante, se pueden pensar que los datos guardados en cada unade estas son un registro. Estas clases contienen variables individuales que representan los camposde datos.

Los registros son agrupados para crear archivos. Archivos de datos estructurados consisten deregistros relacionados entre ellos, tal como un archivo del personal de una empresa que contieneun registro por cada empleado. La cantidad de registros de un archivo puede ser de unos cuantosregistros hasta de millones. Un archivo de datos puede ser usado como un archivo de accesosecuencial cuando cada registro es accedido uno despues de otro en el orden en el cual fueronguardados. La mayorıa de las veces, cada registro es guardado en orden usando el valor de alguncampo, por ejemplo por el numero de seguridad social. Cuando los registros no son usados ensecuencia, el archivo es usado como archivo de acceso aleatorio.

Cuando los registros estan guardados en archivo de datos, sus campos pueden estar organizados enuna lınea, o un caracter puede ser usado para separarlos. Un archivo de valores separados porcoma o CSV es uno en el cual cada valor en un registro esta separado del siguiente por una coma.Este formato es empleado en bases de datos y hojas de calculo.

Antes de que una aplicacion pueda usar un archivo de datos, esta debera abrir el archivo. Unaaplicacion Java abre un archivo creando un objeto y asociandole un flujo de bytes. De igualmanera, cuando se termina de usar un archivo, el programa debera cerrar el archivo para queya no siga disponible para la aplicacion. Si se falla al cerrar un archivo de entrada, uno en elcual se estan leyendo datos, usualmente no hay consecuencias; los datos todavıa existiran en elarchivo. Pero si se falla al cerrar un archivo de salida, uno en el cual se estan escribiendo datos,los datos podrıan hacerse inaccesibles. Siempre se debera cerrar cada archivo que se abra, y sedebera cerrar tan pronto como ya no se ocupe. Cuando se deja un archivo abierto sin razon, esteconsume recursos del sistema, y el rendimiento del sistema decrece. Podrıa ser tambien que otroprograma este esperando para usar el archivo, como en una red de computadoras.

Java ve un archivo de registros como una serie de bytes. Cuando se realiza una operacion deentrada en una aplicacion, esto se puede ver como bytes yendo en el programa desde un dispositivode entrada a traves de un flujo o stream, el cual funciona como una tuberıa o canal. Cuando serealiza salida, algunos bytes salen fuera de la aplicacion a traves de otro flujo a un dispositivo desalida. Un flujo es un objeto, y al igual que otros objetos, los flujos tienen datos y metodos. Losmetodos permiten realizar acciones como abrir, cerrar, leer, y escribir.

La mayorıa de los flujos van en una sola direccion, cada flujo es de entrada o salida. Se podrıanabrir varios flujos simultaneamente en una aplicacion.

11

Page 12: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

Las operaciones de entrada y salida son las mas lentas en cualquier sistema de computo por laslimitaciones impuestas por el hardware. Por esa razon, los programadores profesionales frecuente-mente usan bufers. Un bufer es una localidad de memoria donde los bytes estan guardados despuesde ser escritos logicamente, pero antes de ser enviados al dispositivo. Usar un bufer para acumularentrada o salida antes de realizar el comando de E/S mejora el rendimiento del programa. Cuandose usa un bufer de salida, en ocasiones se vacıa antes de cerrarlo. El vaciar un bufer de memoriahace que se limpie cualquier byte que haya sido enviado a un bufer para salida pero que todavıano ha sido sacado a un dispositivo de hardware.

4. Clases entrada/salida

Enseguida se muestra una relacion jerarquica parcial de algunas de las clases Java usadas paraoperaciones de entrada y salida (E/S); este muestra que InputStream, OutputStream, y Reader

son subclases de la clase Object. Estas tres subclases son abstractas teniendo metodos que debenser anuladas en sus clases hijas. Las capacidades de estas clases estan resumidas en cuadro 2.

Object

|

+--InputStream

| |

| +--FileInputStream

| |

| +--FilterInputStream

| |

| +--BufferedInputStream

|

+--OutputStream

| |

| +--FileOutputStream

| |

| +--FilterOutputStream

| |

| +--BufferedOutputStream

| |

| +--PrintStream

|

+--Reader

|

+--BufferedReder

|

+--BufferedWriter

La clase OutputStream puede ser usada para producir salida. El cuadro 3 muestra algunos de losmetodos comunes de la clase. Se puede usar OutputStream para escribir todos los bytes de unarreglo o una parte. Cuando se termina de usar un OutputStream, se debe vaciar y cerrar.

12

Page 13: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

Clase Descripcion

InputStream Clase abstracta que contiene metodos para realizar entrada.FileInputStream Hija de InputStream que tiene capacidad para leer de los archi-

vos de disco.FilterInputStream Contiene algunos otros flujos de entrada, los cuales son usados

como la fuente base de datos, posiblemente transformando losdatos, o agregando funcionalidad adicional.

BufferedInputStream Hija de FilterInputStream, que a su vez es hija deInputStream; BufferedInputStream maneja la entrada del dis-positivo de entrada estandar (o defecto) de un sistema, general-mente el teclado.

OutputSream Clase abstracta que contiene metodos para realizar la salida.FileOutputStream Hija de OutputStream que permite escribir a archivos de disco.FilterOutputStream Es la superclase de todas las clases que filtran los flujos de salida.

Estos flujos estan en la cima de algun flujo de salida ya existente(el flujo de salida subyacente) el cual lo usa como su drenajebasico de datos, pero posiblemente transformando los datos oproporcionando funcionalidad adicional.

BufferedOutputStream Hija de FilterOutputStream, la cual a su vez es hija deOutputStream; BufferedOutputStream maneja la salida del dis-positivo de salida estandar (o defecto) de un sistema, usualmenteel monitor.

PrintStream Hija de FilterOutputStream, la cual es a su vez hija deOutputStream; System.out es un objeto PrintStream.

Reader Clase abstracta para leer flujos de caracteres; los unicos meto-dos que una subclase debe implementar son read(char[], int,

int) y close().BufferedReader Lee texto de un flujo de caracteres de entrada, almacenando en el

bufer caracteres para contar con lectura eficiente de caracteres,arreglos, y lıneas.

BufferedWriter Escribe texto a un flujo de caracteres de entrada, almacenan-do en el bufer caracteres para contar con escritura eficiente decaracteres, arreglos, y lıneas.

Cuadro 2: Descripcion de las clases seleccionadas usadas para entrada y salida

Metodo OutputStream Descripcion

void close() Cierra el flujo de salida y libera cualquier recursodel sistema asociado con el flujo.

void flush() Vacıa el flujo de salida; si algunos bytes estan en elbuffer, estos son escritos.

void write(btye[] b) Escribe todos los bytes al flujo de salida del arreglode byte especificado.

void write(btye[] b, int desp,

int tam)

Escribe bytes al flujo de salida del arreglo especi-ficado de byte iniciando en la posicion desp parauna cantidad tam de caracteres.

Cuadro 3: Descripcion de las clases seleccionadas usadas para entrada y salida

13

Page 14: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

La clase System de Java contiene un objeto PrintStream llamado System.out, el cual ha sido usadocon los metodos print() y println(). La clase System tambien define otro objeto PrintStream

llamado System.err. La salida de ambos objetos PrintStream pueden ir al mismo dispositivo, comosucede habitualmente. System.err es reservado para mensajes de error y System.out es para salidavalida. Estos se puede redirigir a otra localidad, como un archivo de disco o una impresora.

Se puede crear un objeto OutputStream propio y asignarlo a System.out, pero no se necesita hacer.La aplicacion SalidaAPantalla, codigo 7, muestra como se debe hacer. Se declara una variableString para tener las calificaciones de letra permitidas en un curso. Luego, el metodo getBytes()

convierte el String a un arreglo byte. Un objeto OutputStream es declarado, y System.out le esasignado en un bloque try. El metodo write() acepta el arreglo byte y lo manda al dispositivode salida, y luego el flujo de salida es vaciado y cerrado.

1 import java . i o . ∗ ;2 public class Sal idaAPanta l la {3 public stat ic void main ( St r ing [ ] a rgs ) {4 St r ing s = ”ABCDEF” ;5 byte [ ] datos = s . getBytes ( ) ;6 OutputStream s a l i d a = null ;7 try {8 s a l i d a = System . out ;9 s a l i d a . wr i t e ( datos ) ;

10 s a l i d a . f l u s h ( ) ;11 s a l i d a . c l o s e ( ) ;12 }13 catch ( Exception e ) {14 System . out . p r i n t l n ( ”Mensaje : ” + e ) ;15 }16 }17 }

Codigo 7: La clase SalidaAPantalla.

Escribir a un archivo

En vez de asignar el dispositivo de salida estandar al OutputStream, como se hace en la aplicacionSalidaAPantalla, codigo 7, se puede hacer la asignacion a un archivo. Para realizarlo se construyeun objeto BufferedOutputStream y se asigna a la referencia OutputStream. Si se quiere cambiarun dispositivo de salida de una aplicacion solo se requiere modificar este para asignar un nuevoobjeto al OutputStream. Java permite asignar un archivo a un objeto Stream ası la pantalla desalida y el archivo de salida trabajan en la misma forma.

Se puede crear un archivo de escritura usando el metodo newOutputStream() de la clase Files

y pasandole un argumento Path y una StandardOpenOption. El metodo crea un archivo si estetodavıa no existıa, abre el archivo para escritura, y regresa un OutputStream que puede ser usadopara escribir bytes al archivo. El cuadro 4 muestra los argumentos StandardOpenOption que puedenusarse como el segundo argumento del metodo newOutputStream. Si no se indica alguna opciony el archivo no existe, se crea un archivo nuevo, y si el archivo existe, este se trunca, lo anteriores equivalente a usar las opciones CREATE y TRUNCATE EXISTING. Si se quiere agregar a un archivoexistente, o crear el archivo si este no existe inicilmente usar las opciones APPEND y CREATE. Si se

14

Page 15: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

usa solo APPEND y el archivo no existe, se genera una excepcion.

StandardOpenOption Descripcion

WRITE Abre el archivo para escritura.APPEND Agrega nuevos datos al final del archivo; usar esta opcion con

WRITE o CREATE.TRUNCATE EXISTING Trunca el archivo existente a cero bytes ası el contenido del ar-

chivo es reemplazado; usar esta opcion con WRITE.CREATE NEW Crea un nuevo archivo solo si este no existe; lanzando una ex-

cepcion si el archivo ya existe.CREATE Abre un archivo si existe o crea uno nuevo si no existe.DELETE ON CLOSE Borra el archivo cuando el flujo es cerrado; empleada con archivos

temporales que existen mientras se ejecuta el programa.

Cuadro 4: Constantes StandardOpenOption seleccionadas.

La aplicacion SalidaAArchivo, codigo 8, escribe un String de bytes a un archivo. Las diferenciasrespecto a la aplicacion SalidaAPantalla, codigo 7, se resumen enseguida:

Se usan sentencias adicionales import, lıneas 2 y 3.

El nombre de la clase esta cambiado, lınea 4.

Un Path es declarado para el archivo grados.txt, lınea 6.

En vez de asignar System.out a la referencia OutputStream, un objeto BufferedOutputStreames asignado, lınea 11.

1 import java . i o . ∗ ;2 import java . n io . f i l e . ∗ ;3 import stat ic java . n io . f i l e . StandardOpenOption . ∗ ;4 public class SalidaAArchivo {5 public stat ic void main ( St r ing [ ] a rgs ) {6 Path arch ivo = Paths . get ( ” grados . txt ” ) ;7 St r ing s = ”ABCDEF” ;8 byte [ ] datos = s . getBytes ( ) ;9 OutputStream s a l i d a = null ;

10 try {11 s a l i d a = new12 BufferedOutputStream ( F i l e s . newOutputStream ( archivo , CREATE) ) ;13 s a l i d a . wr i t e ( datos ) ;14 s a l i d a . f l u s h ( ) ;15 s a l i d a . c l o s e ( ) ;16 }17 catch ( Exception e ) {18 System . out . p r i n t l n ( ”Mensaje : ” + e ) ;19 }20 }21 }

Codigo 8: Aplicacion SalidaAArchivo.

15

Page 16: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

Leer desde un archivo

Se usa un InputStream de forma similar a un OutputStream. Si se quiere, se puede crear unInputStream, asignandole System.in, y usando el metodo read() con el objeto creado para recu-perar la entrada del teclado. Sin embargo, es mas eficiente usar la clase Scanner para la entradadel teclado y mejor usar la clase InputStream para entrada de datos que han sido guardados enun archivo.

Se puede usar el metodo newInputStream() de la clase Files para abrir un archivo para lectura.El metodo acepta un parametro Path y devuelve un flujo que puede leer bytes de un archivo. Laaplicacion LeerArchivo, codigo 9, lee el archivo grados.txt que fue creado previamente. El Pathes declarado, un InputStream es declarado usando el Path, y en la lınea 8 un flujo es asignado ala referencia InputStream.

Nota. Si se necesitan leer multiples lıneas del archivo se podrıa usar un ciclo tal como el mostrado

enseguida. El ciclo continuamente lee y muestra lıneas del archivo hasta que el metodo readLine()

regresa null para indicar que no hay mas datos disponibles.

while (s = lector.readLine() != null)

System.out.println(s);

En la lınea 9 de la clase LeerArchivo, un BufferedReader es declarado. Un BufferedReader leeuna lınea de texto de un flujo entrada-caracter, almacenar caracteres en el bufer hace que la lecturasea mas eficiente.

1 import java . i o . ∗ ;2 import java . n io . f i l e . ∗ ;3 public class LeerArchivo {4 public stat ic void main ( St r ing [ ] a rgs ) {5 Path arch ivo = Paths . get ( ” grados . txt ” ) ;6 InputStream entrada = null ;7 try {8 entrada = F i l e s . newInputStream ( arch ivo ) ;9 BufferedReader l e c t o r = new BufferedReader (

10 new InputStreamReader ( entrada ) ) ;11 St r ing s = null ;12 s = l e c t o r . readLine ( ) ;13 System . out . p r i n t l n ( s ) ;14 l e c t o r . c l o s e ( ) ;15 }16 catch ( Exception e ) {17 System . out . p r i n t l n ( ”Mensaje : ” + e ) ;18 }19 }20 }

Codigo 9: Clase LeerArchivo.

Cuando se usa la clase BufferedReader, se debe importar del paquete java.io en el programa.La siguiente tabla muestra algunos metodos utiles de BufferedReader.

16

Page 17: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

Metodo BufferedReader Descripcion

close() Cierra el flujo y cualquier recurso asociado con este.read() Lee un solo caracter.read(char[] buffer, int de,

int can)

Lee caracteres en una porcion de un arreglo desdela posicion de para can caracteres.

readLine() Lee una lınea de texto.skip(long n) Salta el numero especificado de caracteres.

Cuadro 5: Metodos BufferedReader.

5. Archivos secuenciales de datos

En ocasiones se quiere guardar algo mas que un String en un archivo. Se podrıa tener un archivode datos de registros personales que incluyan un numero de identificacion, un nombre, y un salariopara cada empleado de una organizacion. La aplicacion EscribirArchivoEmpleado, codigo 10, leenumeros de identificacion, nombres y salarios desde el teclado y los manda, separados con comas,a un archivo.

1 import java . n io . f i l e . ∗ ;2 import java . i o . ∗ ;3 import stat ic java . n io . f i l e . StandardOpenOption . ∗ ;4 import java . u t i l . Scanner ;5 public class Escr ibirArchivoEmpleado {6 public stat ic void main ( St r ing [ ] a rgs ) {7 Scanner entrada = new Scanner ( System . in ) ;8 Path arch ivo = Paths . get ( ” empleados . txt ” ) ;9 St r ing s = ”” ;

10 St r ing de l im i tador = ” , ” ;11 int id ;12 St r ing nombre ;13 double s a l a r i o ;14 f ina l int SALIR = 999 ;15 try {16 OutputStream s a l i d a = new17 BufferedOutputStream ( F i l e s . newOutputStream ( archivo , CREATE) ) ;18 Buf feredWriter e s c r i t o r = new19 Buf feredWriter (new OutputStreamWriter ( s a l i d a ) ) ;20 System . out . p r i n t ( ” I n g r e s a r numero i d e n t i f i c a d o r >> ” ) ;21 id = entrada . next Int ( ) ;22 while ( id != SALIR) {23 System . out . p r i n t ( ” I n g r e s a r nombre de l empleado #” +24 id + ” >> ” ) ;25 entrada . nextLine ( ) ;26 nombre = entrada . nextLine ( ) ;27 System . out . p r i n t ( ” I n g r e s a r s a l a r i o >> ” ) ;28 s a l a r i o = entrada . nextDouble ( ) ;29 s = id + de l im i tador + nombre + de l im i tador + s a l a r i o ;30 e s c r i t o r . wr i t e ( s , 0 , s . l ength ( ) ) ;31 e s c r i t o r . newLine ( ) ;32 System . out . p r i n t ( ” I n g r e s a r s i g u i e n t e numero i d e n t i f i c a d o r o ” +33 SALIR + ” para terminar >> ” ) ;34 id = entrada . next Int ( ) ;

17

Page 18: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

35 }36 e s c r i t o r . c l o s e ( ) ;37 }38 catch ( Exception e ) {39 System . out . p r i n t l n ( ”Mensaje : ” + e ) ;40 }41 }42 }

Codigo 10: La clase EscribirArchivoEmpleado.

En la aplicacion EscribirArchivoEmpleado, codigo 10, en las lıneas 18—19 se crea un Buffered-

Writer llamado escritor. La clase BufferedWriter es la contraparte de BufferedReader. Estaescribe texto a un flujo de salida, almancenando en el bufer los caracteres. La clase tiene tres metodoswrite() sobrecargados que proporcionan escritura eficiente de caracteres de un String, de arregloschar, y de un caracter. El cuadro 6 contiene los metodos definidos en la clase BufferedWriter.

Metodo BufferedWriter Descripcion

close() Cierra el flujo, vaciandolo primero.flush() Vacıa el flujo.newline() Escribe un separador de lınea.write(String s, int de, int can) Escribe un String desde la posicion de para

una longitud can.write(char[] a, int de, int can) Escribe un arreglo char desde la posicion de

para una longitud can.write(int c) Escribe un solo caracter.

Cuadro 6: Metodos BufferedWriter.

En la aplicacion EscribirArchivoEmpleado, los String de los datos de empleado son construıdosdentro de un ciclo que se ejecuta mientras el usuario no ingrese el valor SALIR. Cuando el Stringesta completo, con numero de identificacion, nombre y salario separados con comas, el String esenviado al escritor con lo indicado en la lınea 30. El metodo write() acepta el String desde laposicion cero con su tamano completo.

Despues de que el String es escrito, se escribe enseguida el caracter de nueva lınea del sistema.Un archivo de datos podrıa no requerir un caracter de nueva lınea despues de cada registro, cadanuevo registro podrıa estar separado con una coma o cualquier otro caracter unico que no fueusado como parte de los datos, el usar nueva lınea facilita la lectura del archivo. Como no todaslas plataformas usan ’\n’ para separar las lıneas, la clase BufferedWriter contiene el metodonewLine() que usa el separador de lınea actual de la plataforma. Tambien se podrıa escribir elvalor de System.getProperty("line.separator"), que es como lo hace el metodo newLine().

Cualquiera de los metodos de entrada o salida en el programa EscribirArchivoEmpleado podrıalanzar una excepcion, ası que este codigo es puesto en bloque try.

La aplicacion LeerArchivoEmpleado, codigo 11, lee el archivo empleado.txt creado por la aplicacionEscribirArchivoEmpleado. El programa declara un InputStream para el archivo, luego crea unBufferedReader usando el InputStream. La primera lınea es leıda en un String; mientras elmetodo readLine() no devuelva null, el String es mostrado y una nueva lınea es leıda.

18

Page 19: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

1 import java . i o . ∗ ;2 import java . n io . f i l e . ∗ ;3 public class LeerArchivoEmpleado {4 public stat ic void main ( St r ing [ ] a rgs ) {5 Path arch ivo = Paths . get ( ” empleados . txt ” ) ;6 St r ing s = ”” ;7 try {8 InputStream entrada = new9 BufferedInputStream ( F i l e s . newInputStream ( arch ivo ) ) ;

10 BufferedReader l e c t o r = new BufferedReader (11 new InputStreamReader ( entrada ) ) ;12 s = l e c t o r . readLine ( ) ;13 while ( s != null ) {14 System . out . p r i n t l n ( s ) ;15 s = l e c t o r . readLine ( ) ;16 }17 l e c t o r . c l o s e ( ) ;18 }19 catch ( Exception e ) {20 System . out . p r i n t l n ( ”Mensaje : ” + e ) ;21 }22 }23 }

Codigo 11: La clase LeerArchivoEmpleado.

Otras aplicaciones podrıan no querer usar el archivo de datos solo como String como lo hace laaplicacion LeerArchivoEmpleado. La aplicacion LeerArchivoEmpleado2, codigo 12, tambien leedel archivo String pero las divide en campos usables. El metodo split() de la clase String

acepta un argumento que identifica el delimitador de campos, para los ejemplos dados, una coma, yregresa un arreglo de String. Cada elemento del arreglo tiene un campo. Luego los metodos comoparseInt() o parseDouble() pueden ser usados para obtener del String dividido sus respectivostipos de datos.

1 import java . i o . ∗ ;2 import java . n io . f i l e . ∗ ;3 public class LeerArchivoEmpleado2 {4 public stat ic void main ( St r ing [ ] a rgs ) {5 Path arch ivo = Paths . get ( ” empleados . txt ” ) ;6 St r ing [ ] a r r e g l o = new St r ing [ 3 ] ;7 St r ing s = ”” ;8 St r ing de l im i tador = ” , ” ;9 int id ;

10 St r ing nombre ;11 double s a l a r i o ;12 double neto ;13 f ina l double HORAS SEMANA = 40 ;14 double t o t a l =0.0 ;15 try {16 InputStream entrada = new17 BufferedInputStream ( F i l e s . newInputStream ( arch ivo ) ) ;18 BufferedReader l e c t o r = new19 BufferedReader (new InputStreamReader ( entrada ) ) ;20 s = l e c t o r . readLine ( ) ;

19

Page 20: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

21 while ( s != null ) {22 a r r e g l o = s . s p l i t ( de l im i tador ) ;23 id = I n t e g e r . pa r s e In t ( a r r e g l o [ 0 ] ) ;24 nombre = a r r e g l o [ 1 ] ;25 s a l a r i o = Double . parseDouble ( a r r e g l o [ 2 ] ) ;26 neto = s a l a r i o ∗ HORAS SEMANA;27 System . out . p r i n t l n ( ” id #” + id + ” ” + nombre +28 ” $” + s a l a r i o + ” $” + neto ) ;29 t o t a l += neto ;30 s = l e c t o r . readLine ( ) ;31 }32 l e c t o r . c l o s e ( ) ;33 }34 catch ( Exception e ) {35 System . out . p r i n t l n ( ”Mensaje : ” + e ) ;36 }37 System . out . p r i n t l n ( ” El pago t o t a l de l a nomina es $” + t o t a l ) ;38 }39 }

Codigo 12: La clase LeerArchivoEmpleado2.

Conforme cada registro es leıdo y dividido en la clase LeerArchivoEmpleado2, con el campo salariose calcula el pago bruto del empleado en una jornada de 40 horas a la semana. Luego el pago brutoes acumulado para obtener el pago total de la nomina despues de que todos los datos han sidoprocesados.

6. Archivos de acceso aleatorio

Los negocios guardan datos en orden secuencial cuando usan los registros para procesamientopor lotes, lo cual involucra realizar las mismas tareas con muchos registros, uno despues de otro.Por ejemplo, cuando una empresa genera recibos de pagos, los registros para el perıodo de pago sonreunidos en un lote y los recibos son calculados e impresos en secuencia. No importa cual recibosea generado primero porque los recibos son enviados por correo.

Un acceso secuencial es ineficiente para muchas aplicaciones. Estas aplicaciones, como aplicacionesen tiempo real, requieren que un registro sea accedido inmediatamente mientras un cliente espera.Un programa en el cual el usuario hace peticiones directas es un programa interactivo. Unrepresentante del servicio al cliente requiere archivos de acceso aleatorio, tambien llamados deacceso directo o de acceso instantaneo, en vez de archivos de acceso secuencial. Ya que tomarıamucho tiempo acceder los registros de los clientes si estos deben ser leıdos secuencialmente.

Se puede usar la clase FileChannel para crear archivos de acceso aleatorio. Un objeto canal dearchivo es un medio para leer y escribir a un archivo. Un canal de archivo es buscable, es decir, sepuede buscar por una localidad especıfica del archivo y las operaciones pueden iniciar en cualquierposicion especificada. El cuadro 7 muestra algunos metodos FileChannel.

Varios metodos del cuadro 7 usan un objeto ByteBuffer. Un ByteBuffer es un lugar para bytesque estan esperando ser leıdos o escritos. Un arreglo de bytes puede ser envuelto, o empacado, enun ByteBuffer usando el metodo wrap() de ByteBuffer. Envolviendo un arreglo de bytes en un

20

Page 21: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

Metodo FileChannel Descripcion

FileChannel open(Path arch,

OpenOption... opciones)

Abre o crea un archivo, devolviendo un canal dearchivo.

long position() Devuelve la posicion del canal de archivo.FileChannel position(long

nuevaPosicion)

Pone la nueva posicion del canal de archivo.

int read(ByteBuffer bufer) Lee una secuencia de bytes del canal en el bufer.long size() Devuelve el tamano actual del archivo de canal.int write(ByteBuffer bufer) Escribe una secuencia de bytes al canal desde el

bufer.

Cuadro 7: Metodos FileChannel.

bufer hace que los cambios hechos al bufer tambien sean hechos al arreglo, y viceversa. Crear unFileChannel para escritura de datos aleatoria requiere crear un ByteBuffer y otros pasos:

Se puede usar el metodo newByteChannel() de la clase Files para obtener un ByteChannel

para un Path. El metodo newByteChannel acepta argumentos Path y StandardOpenOption

que indicar como el archivo sera abierto.

El ByteChannel regresado por el metodo newByteChannel() puede entonces ser convertidoa un FileChannel usando una sentencia parecida a la siguiente:

FileChannel fc = (FileChannel)Files.newByteChannel(archivo, READ, WRITE);

Se puede crear un arreglo byte. El arreglo byte se puede construir desde un String usandoel metodo getBytes() como sigue:

String s = "ABC";

byte[] datos = s.getBytes();

El arreglo byte puede ser envuelto en un ByteBuffer de esta forma:

ByteBuffer salida = ByteBuffer.wrap(datos);

Luego el ByteBuffer lleno puede ser escrito al FileChannel declarado como en la siguienteinstruccion:

fc.write(salida);

Se puede revisar si el contenido de un ByteBuffer ha sido usado mediante el metodo has-

Remaining().

Despues de escribir el contenido de un ByteBuffer, se puede escribir el mismo contenidodel ByteBuffer nuevamente usando el metodo rewind() para reposicionar el ByteBuffer alinicio del bufer.

21

Page 22: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

La aplicacion PruebaAccesoAleatorio, codigo 13 usa los pasos previos para declarar un archivo yescribir algunos bytes aleatoriamente en las posiciones 0, 22, y 12.

1 import java . i o . ∗ ;2 import java . n io . f i l e . ∗ ;3 import java . n io . channe l s . Fi leChannel ;4 import java . n io . ByteBuffer ;5 import stat ic java . n io . f i l e . StandardOpenOption . ∗ ;6 public class PruebaAccesoAleator io {7 public stat ic void main ( St r ing [ ] a rgs ) {8 Path arch ivo = Paths . get ( ”numeros . txt ” ) ;9 crearArch ivo ( arch ivo ) ;

10 St r ing s = ”ABC” ;11 byte [ ] datos = s . getBytes ( ) ;12 ByteBuffer s a l i d a = ByteBuffer . wrap ( datos ) ;13 Fi leChannel f c = null ;14 try {15 f c = ( Fi leChannel ) F i l e s . newByteChannel ( archivo , READ, WRITE) ;16 f c . p o s i t i o n ( 0 ) ;17 while ( s a l i d a . hasRemaining ( ) )18 f c . wr i t e ( s a l i d a ) ;19 s a l i d a . rewind ( ) ;20 f c . p o s i t i o n ( 2 2 ) ;21 while ( s a l i d a . hasRemaining ( ) )22 f c . wr i t e ( s a l i d a ) ;23 s a l i d a . rewind ( ) ;24 f c . p o s i t i o n ( 1 6 ) ;25 while ( s a l i d a . hasRemaining ( ) )26 f c . wr i t e ( s a l i d a ) ;27 f c . c l o s e ( ) ;28 }29 catch ( Exception e ) {30 System . out . p r i n t l n ( ”Mensaje : ” + e ) ;31 }32 }33 public stat ic void crearArch ivo ( Path arch ivo ) {34 St r ing s = ” 0123456789012345678901234567890123456789 ” ;35 try {36 OutputStream s a l i d a = new37 BufferedOutputStream ( F i l e s . newOutputStream ( archivo , CREATE) ) ;38 s a l i d a . wr i t e ( s . getBytes ( ) ) ;39 s a l i d a . f l u s h ( ) ;40 s a l i d a . c l o s e ( ) ;41 }42 catch ( Exception e ) {43 System . out . p r i n t l n ( ”Mensaje : ” + e ) ;44 }45 }46 }

Codigo 13: La clase PruebaAccesoAleatorio.

22

Page 23: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

7. Escritura de registros en archivos de acceso aleatorio

La escritura de caracteres en localidades aleatorias de archivo de texto, como en la apliacionPruebaAccesoAleatorio, es de valor limitado. Cuando se guardan registros en un archivo, el ac-ceso es mas util por registro, como acceder el quinto registro, en vez de recuperar el quinto byte.Para lograr lo anterior, se debe multiplicar la posicion del registro que se quiere acceder por eltamano del registro. Por ejemplo, si se guardan registros que son de tamano 50 bytes, el primerregistro esta en la posicion cero, el segundo registro en la posicion 50, el tercero en la posicion 100,y ası sucesivamente. Es decir, se puede acceder el n-esimo registro en un FileChannel llamado fc

con la siguiente sentencia:

fc.position((n - 1) * 50);

Una aproximacion para escribir un archivo de acceso aleatorio es colocar los registros en el archivousando un campo llave. Un campo llave es el campo en un registro que hace al registro unico delresto. Por ejemplo, suponer que se quiere guardar numeros identificador de empleado, apellidos, ysalarios en un archivo de acceso aleatorio. En un archivo de empleados, varios registros podrıantener el mismo apellido o salario, pero cada registro tiene un numero identificador de empleado,ası que este campo puede ser el campo llave.

El primer paso en la creacion del archivo empleado de acceso aleatorio es la creacion del archivoque guarde los registros por defecto—por ejemplo, con ceros para los identificadores y los salariosy blancos para los apellidos. En este caso, se supone que cada identificador es de tres dıgitos. Laaplicacion CrearArchivoVacioEmpleados, codigo 14, crea 1,000 registros del tipo descrito.

1 import java . i o . ∗ ;2 import java . n io . ByteBuffer ;3 import java . n io . f i l e . ∗ ;4 import stat ic java . n io . f i l e . StandardOpenOption . ∗ ;5 public class CrearArchivoVacioEmpleados {6 public stat ic void main ( St r ing [ ] a rgs ) {7 Path arch ivo = Paths . get ( ” emp l eado s a l e a to r i o . txt ” ) ;8 St r ing s = ” 000 , , 000 .00 ” +9 System . getProperty ( ” l i n e . s epa ra to r ” ) ;

10 f ina l int NUM REGS = 1000 ;11 try {12 OutputStream s a l i d a = new13 BufferedOutputStream ( F i l e s . newOutputStream ( archivo , CREATE) ) ;14 Buf feredWriter e s c r i t o r = new15 Buf feredWriter (new OutputStreamWriter ( s a l i d a ) ) ;16 for ( int cont = 0 ; cont < NUM REGS; ++cont )17 e s c r i t o r . wr i t e ( s , 0 , s . l ength ( ) ) ;18 e s c r i t o r . c l o s e ( ) ;19 }20 catch ( Exception e ) {21 System . out . p r i n t l n ( ”Mensaje : ” + e ) ;22 }23 }24 }

Codigo 14: Aplicacion CrearArchivoVacioEmpleados.

23

Page 24: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

En las lıneas 8—9 del codigo 14, un String que representa un registro por defecto es declarado.El numero de empleado de tres dıgitos es puesto a ceros, el apellido consiste de veinte blancos, yel salario es 000.00, ademas la cadena termina con el valor del separador de lınea del sistema. Unarreglo byte es construido del String y envuelto en un bufer. Luego un archivo es abierto en modoCREATE y un BufferedWriter es establecido.

En las lıneas 16—17 del codigo 14, un ciclo se ejecuta mil veces. Dentro del ciclo, la cadena pordefecto empleado es pasada al metodo write() del objeto BufferedWriter.

Los campos por defecto en el archivo base de acceso aleatorio se pueden inicializar con los valoresque sean mas convenientes para la organizacion. El unico requisito en la inicializacion es que losregistros por defecto sean reconocidos como tales.

Despues de crear el archivo por defecto base, se puede reemplazar cualquiera de sus registros condatos para un empleado actual. La aplicacion CrearUnRegistroAccesoAleatorio, codigo 15, creaun solo registro empleado definido en la sentencia de las lıneas 9—10. El registro es para empleado002 con apellidos Silvano Aureoles y un salario de 987.65. En la lınea 11, el tamano de la cadenaes asignado a TAM REG. En este caso el tamano es 32, ya que cada caracter, incluyendo las comasdelimitadoras, y un byte para el valor del separador de lınea dado por System.getProperty().Despues el FileChannel es establecido, el registro es escrito al archivo en la posicion que inicia endos veces el tamano del registro. El valor dos es codificado en esta aplicacion porque el numeroidenticador de empleados es 002.

1 import java . i o . ∗ ;2 import java . n io . ByteBuffer ;3 import java . n io . channe l s . Fi leChannel ;4 import java . n io . f i l e . ∗ ;5 import stat ic java . n io . f i l e . StandardOpenOption . ∗ ;6 public class CrearUnRegistroAccesoAleator io {7 public stat ic void main ( St r ing [ ] a rgs ) {8 Path arch ivo = Paths . get ( ” emp l eado s a l e a to r i o . txt ” ) ;9 St r ing s = ” 002 , S i lvano Aureo les , 987 .65 ” +

10 System . getProperty ( ” l i n e . s epa ra to r ” ) ;11 f ina l int TAM REG = s . l ength ( ) ;12 byte [ ] datos = s . getBytes ( ) ;13 ByteBuffer s a l i d a = ByteBuffer . wrap ( datos ) ;14 Fi leChannel f c = null ;15 try {16 f c = ( Fi leChannel ) F i l e s . newByteChannel ( archivo , READ, WRITE) ;17 f c . p o s i t i o n (2 ∗ TAM REG) ;18 f c . wr i t e ( s a l i d a ) ;19 f c . c l o s e ( ) ;20 }21 catch ( Exception e ) {22 System . out . p r i n t l n ( ”Mensaje : ” + e ) ;23 }24 }25 }

Codigo 15: Aplicacion CrearUnRegistroAccesoAleatorio.

Un programa que inserte un registro de empleado codificado en un archivo de datos no es muy util.El programa CrearEmpleadosAccesoAleatorio, codigo 16, acepta cualquier cantidad de registros

24

Page 25: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

ingresados por el usuario y los escribe a un archivo dentro de un ciclo. En la lınea 26 cada valor dedato de empleado es aceptado desde el teclado como un String y convertido a un entero usandoel metodo parseInt(). Luego, en la sentencia de la lınea 36 la posicion del registro deseado escalculada multiplicando el numero identificador por el tamano del registro.

1 import java . i o . ∗ ;2 import java . n io . ByteBuffer ;3 import java . n io . channe l s . Fi leChannel ;4 import java . n io . f i l e . ∗ ;5 import stat ic java . n io . f i l e . StandardOpenOption . ∗ ;6 import java . u t i l . Scanner ;7 public class CrearEmpleadosAccesoAleator io {8 public stat ic void main ( St r ing [ ] a rgs ) {9 Scanner entrada = new Scanner ( System . in ) ;

10 Path arch ivo = Paths . get ( ” emp l eado s a l e a to r i o . txt ” ) ;11 St r ing s = ” 000 , , 000 .00 ” +12 System . getProperty ( ” l i n e . s epa ra to r ” ) ;13 f ina l int TAM REG = s . l ength ( ) ;14 Fi leChannel f c = null ;15 St r ing de l im i tador=” , ” ;16 St r ing idCadena ;17 int id ;18 St r ing nombre ;19 St r ing s a l a r i o ;20 f ina l St r ing SALIR = ”999” ;21 try {22 f c = ( Fi leChannel ) F i l e s . newByteChannel ( archivo , READ, WRITE) ;23 System . out . p r i n t ( ” I n g r e s a r numero i d e n t i f i c a d o r (3 l u g a r e s ) >> ” ) ;24 idCadena = entrada . nextLine ( ) ;25 while ( ! ( idCadena . equa l s (SALIR ) ) ) {26 id = I n t e g e r . pa r s e In t ( idCadena ) ;27 System . out . p r i n t ( ” I n g r e s a r a p e l l i d o s para empleado #” +28 id + ” >> (20 l u g a r e s ) ” ) ;29 nombre = entrada . nextLine ( ) ;30 System . out . p r i n t ( ” I n g r e s a r s a l a r i o >> (6 l u g a r e s ) ” ) ;31 s a l a r i o = entrada . nextLine ( ) ;32 s = idCadena + de l im i tador + nombre + de l im i tador +33 s a l a r i o + System . getProperty ( ” l i n e . s epa ra to r ” ) ;34 byte [ ] datos = s . getBytes ( ) ;35 ByteBuffer s a l i d a = ByteBuffer . wrap ( datos ) ;36 f c . p o s i t i o n ( id ∗ TAM REG) ;37 f c . wr i t e ( s a l i d a ) ;38 System . out . p r i n t ( ” I n g r e s a r s i g u i e n t e numero i d e n t i f i c a d o r o ” +39 SALIR + ” para terminar >> ” ) ;40 idCadena = entrada . nextLine ( ) ;41 }42 f c . c l o s e ( ) ;43 }44 catch ( Exception e ) {45 System . out . p r i n t l n ( ”Mensaje : ” + e ) ;46 }47 }48 }

25

Page 26: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

Codigo 16: La clase CrearEmpleadosAccesoAleatorio.

Para que la aplicacion CrearEmpleadosAccesoAleatorio, codigo 16, se mantenga simple y enfo-cada en la escritura del archivo de acceso aleatorio realiza varias suposiciones:

Un registro de empleado contiene un solo numero identificador, apellidos, y un salario. Enuna aplicacion de la vida real, cada empleado podrıa requerir mas campos de datos, comodireccion, numero telefonico, fecha de contratacion, etc.

Cada numero identificador de empleado es de tres dıgitos. En muchas aplicaciones de la vidareal, estos numeros podrıan ser mas grandes para asegurar valores unicos.

El usuario debera ingresar numeros identificadores y salarios validos. En una aplicacion pro-fesional, esta es una suposicion incorrecta porque el usuario podrıa meter mas dıgitos o ca-racteres no numericos. En la aplicacion no se hace validacion de entrada para mantener elcodigo simple.

El usuario no debera duplicar los numeros identificadores. En una aplicacion real, un campollave debera ser revisado contra todos los campos llave existentes para asegurar que un registroes unico antes de agregarlo al archivo.

Todos los apellidos ingresados deben tener 20 caracteres para que cada registro sea del mismotamano. Solo cuando los tamanos de los registros son uniformes pueden ser usados paracalcular las posiciones de desplazamiento aritmeticamente. En una aplicacion real, se deberanrellenar con espacios los apellidos de menos de 20 caracteres y recortar los que excedan eltamano anterior.

Cada registro de empleado es colocado en la posicion del archivo de acceso aleatorio quees una menos que el numero identificador de empleado. En una aplicacion real, el calculorealizado en un campo llave para determinar el desplazamiento es mas complicada.

8. Lectura de registros en archivos de acceso aleatorio

Si un archivo es creado como archivo de acceso aleatorio, este puede ser procesado tambien enforma secuencial

Acceso secuencial de un archivo aleatorio

El archivo empleados aleatorio.txt creado en la seccion 7 contiene mil registros. Sin embargo,solo unos cuantos contienen datos utiles. Mostrar cada registro del archivo podrıa resultar en muchaslıneas de salida irrelevantes. Tiene mas sentido mostrar solo aquellos registros para los cuales unnumero identificador ha sido insertado. La aplicacion LeerEmpleadosSecuencialmente, codigo17, lee los mil registros secuencialmente con un ciclo while. En la lınea 28 se revisa por numerosidentificadores validos. En este ejemplo se supone que un empleado no tiene un numero identificadorigual a 000, ası la aplicacion solo mostrara aquellos registros cuando el numero identificador sea

26

Page 27: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

diferente de 000. Si 000 es un numero identificador valido entonces se deberıa revisar que el nombreeste en blanco, y tenga un salario de cero.

1 import java . i o . ∗ ;2 import java . n io . f i l e . ∗ ;3 import stat ic java . n io . f i l e . AccessMode . ∗ ;4 public class LeerEmpleadosSecuencialmente {5 public stat ic void main ( St r ing [ ] a rgs ) {6 Path arch ivo = Paths . get ( ” emp l eado s a l e a to r i o . txt ” ) ;7 St r ing [ ] a r r e g l o = new St r ing [ 3 ] ;8 St r ing s = ”” ;9 St r ing de l im i tador = ” , ” ;

10 int id ;11 St r ing cadenaId ;12 St r ing a p e l l i d o s ;13 double s a l a r i o ;14 double neto ;15 f ina l double HORAS SEMANA = 4 0 . ;16 double t o t a l =0.0 ;17 try {18 InputStream entrada = new19 BufferedInputStream ( F i l e s . newInputStream ( arch ivo ) ) ;20 BufferedReader l e c t o r = new21 BufferedReader ( new InputStreamReader ( entrada ) ) ;22 System . out . p r i n t l n ( ) ;23 s = l e c t o r . readLine ( ) ;24 while ( s != null ) {25 a r r e g l o = s . s p l i t ( de l im i tador ) ;26 cadenaId = a r r e g l o [ 0 ] ;27 id = I n t e g e r . pa r s e In t ( cadenaId ) ;28 i f ( id != 0 ) {29 a p e l l i d o s = a r r e g l o [ 1 ] ;30 s a l a r i o = Double . parseDouble ( a r r e g l o [ 2 ] ) ;31 neto = s a l a r i o ∗ HORAS SEMANA;32 System . out . p r i n t l n ( ”# i d e n t i f i c a d o r ” + cadenaId + ” ” +33 a p e l l i d o s + ” $” + s a l a r i o + ” $” + neto ) ;34 t o t a l += neto ;35 }36 s = l e c t o r . readLine ( ) ;37 }38 l e c t o r . c l o s e ( ) ;39 }40 catch ( Exception e ) {41 System . out . p r i n t l n ( ”Mensaje : ” + e ) ;42 }43 System . out . p r i n t l n ( ”El pago t o t a l de l a nomina es $” + t o t a l ) ;44 }45 }

Codigo 17: Aplicacion LeerEmpleadosSecuencialmente.

27

Page 28: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

Acceso arbitrario de un archivo aleatorio

Si solo se quiere mostrar registros usando su campo llave, no es necesario crear un archivo de accesoaleatorio y desperdiciar espacio no necesitado. Se podrıa ordenar los registros usando algunas de lastecnicas vistas en el capıtulo arreglos avanzados. El beneficio de usar un archivo de acceso aleatorioes la habilidad para recuperar un registro especıfico de un archivo directamente, sin tener que pasara traves de otros registros para localizar el registro deseado.

La aplicacion LeerEmpleadosAleatoriamente, codigo 18, permite al usuario ingresar un numeroidentificador de empleado. La aplicacion calcula la posicion del registro en el archivo de datos, unomenos que el numero identificador, y pone el apuntador de archivo en la localidad para iniciarla lectura. Al usuario se le pide un numero identificador, el cual es convertido a un entero con elmetodo parseInt(). La aplicacion no revisa que el numero identificador sea valido. En las lıneas27—28 de la aplicacion la posicion del registro es calculada multiplicando el numero identificadorpor el tamano del registro y luego posicionando el apuntador de archivo en la localidad deseada.Para mantener el ejemplo pequeno, el numero identificador no es revisado para asegurarse que 999o menos. El registro de empleado es recuperado del archivo de datos y mostrado, y luego al usuariose pide por el siguiente numero identificador deseado.

1 import java . i o . ∗ ;2 import java . n io . ByteBuffer ;3 import java . n io . channe l s . Fi leChannel ;4 import java . n io . f i l e . ∗ ;5 import stat ic java . n io . f i l e . StandardOpenOption . ∗ ;6 import java . u t i l . Scanner ;7 public class LeerEmpleadosAleatoriamente {8 public stat ic void main ( St r ing [ ] a rgs ) {9 Scanner t e c l ado = new Scanner ( System . in ) ;

10 Path arch ivo = Paths . get ( ” emp l eado s a l e a to r i o . txt ” ) ;11 St r ing s = ” 000 , , 000 .00 ” +12 System . getProperty ( ” l i n e . s epa ra to r ” ) ;13 f ina l int TAM REG = s . l ength ( ) ;14 byte [ ] datos = s . getBytes ( ) ;15 ByteBuffer s a l i d a = ByteBuffer . wrap ( datos ) ;16 Fi leChannel f c = null ;17 St r ing cadenaId ;18 int id ;19 f ina l St r ing SALIR = ”999” ;20 try {21 f c = ( Fi leChannel ) F i l e s . newByteChannel ( archivo , READ, WRITE) ;22 System . out . p r i n t ( ” I n g r e s a r numero i d e n t i f i c a d o r >> ” ) ;23 cadenaId = tec l ado . nextLine ( ) ;24 while ( ! cadenaId . equa l s ( SALIR ) ) {25 id = I n t e g e r . pa r s e In t ( cadenaId ) ;26 s a l i d a = ByteBuffer . wrap ( datos ) ;27 f c . p o s i t i o n ( id ∗ TAM REG) ;28 f c . read ( s a l i d a ) ;29 s = new St r ing ( datos ) ;30 System . out . p r i n t l n ( ”# id ” + s ) ;31 System . out . p r i n t ( ” I n g r e s a r numero i d e n t i f i c a d o r o ” +32 SALIR + ” para s a l i r >> ” ) ;33 cadenaId = tec l ado . nextLine ( ) ;

28

Page 29: Entrada y salida de archivos - Computación - FISMATcomputo.fismat.umich.mx/computacion/computacion1/actividades/a… · Algunos archivos de texto son archivos de datos como uno que

34 }35 f c . c l o s e ( ) ;36 }37 catch ( Exception e ) {38 System . out . p r i n t l n ( ”Mensaje : ” + e ) ;39 }40 }41 }

Codigo 18: Aplicacion LeerEmpleadosAleatoriamente.

29