Sunteți pe pagina 1din 42

10

tilizar E/S
Conceptos fundamentales:
Concepto de flujo, diferencia entre flujos de bytes y de caracteres.
Clases de flujo de bytes y de caracteres de Java.
Flujos predefinidos.
Utilizar flujos de bytes.
Utilizar flujos de bytes para E/S de archivos.
Cerrar automticamente un archivo con try con recursos.
Leer y escribir datos binarios.
Utilizar archivos de acceso aleatorio.
Utilizar flujos de caracteres.
Utilizar flujos de caracteres para E/S de archivos.
Aplicar envoltorios de tipos de Java para convertir cadenas numricas.
Desde el inicio del libro hemos usado partes del sistema de E/S de Java, como
println ().Sin embargo, lo hemos hecho sin explicaciones formales. Como el sistema
de E/S de Java se basa en una jerarqua de clases, no podamos presentar esta teora
sin analizar primero las clases, la herencia y la excepciones. Ahora es el momento de
examinar el enfoque de Java a E/S con detalle.
IUI 10. Utilizar E/S
Debe saber que el sistema de E/S de Java es extenso, con numerosas clases, inter-
faces y mtodos. Parte de su tamao se debe a que Java define dos sistemas completos
de E/S: uno para E/S de bytes y otro para E/S de caracteres. Aqu no podernos analizar
todos los aspectos de la E/S de Java. (Se necesitara un libro completo.) En este captulo
presentaremos las funciones ms importantes y utilizadas. Afortunadamente, el sistema
de E/S de Java es coherente; una vez familiarizado con los aspectos bsicos, le resultar
sencillo dominar el resto.
Antes de comenzar, recordarle que las clases E/S descritas en el captulo admiten E/S
de consola basada en texto y E/S de archivos. No se usan para crear interfaces grficas
de usuario (GUI). Por ello, no las usaremos para crear aplicaciones con ventanas. No
obstante, Java es compatible con la creacin de estas interfaces. Los fundamentos de la
programacin GUI se presentan en el captulo 14 y en el 15 veremos Swing, el moderno
kit de herramientas GUI de Java.
E/S de Java se basa en flujos
Los programas de Java realizan la E/S a travs de flujos. Un flujo es una abstraccin
que produce o consume informacin. Un flujo se vincula a un dispositivo fsico a travs
del sistema E/S de Java.
Todos los flujos se comportan igual, aunque difieran los dispositivos fsicos a los
que estn vinculados. Por tanto, se pueden aplicar las mismas clases y mtodos E/S a
cualquier tipo de dispositivo. Por ejemplo, los mismos mtodos usados para escribir en
la consola se pueden usar para escribir en disco. Java implementa los flujos en las jerar-
quas de clases definidas en el paquete java. io.
Flujos de bytes y de caracteres
Las versiones modernas de Java definen dos tipos de flujos: de bytes y de caracteres.
(La versin original de Java slo defina el de bytes, pero el de caracteres se adopt rpi-
damente.) Los flujos de bytes permiten procesar la entrada y salida de bytes. Se usan,
por ejemplo, al leer o escribir datos binarios.
Resultan especialmente tiles para trabajar con archivos. Los flujos de caracteres
permiten procesar la entrada y salida de caracteres. Usan Unicode y, por tanto, se pueden
internacionalizar. Adems, en algunos casos, los flujos de caracteres son ms eficaces
que los de bytes.
El hecho de que Java defina dos tipos distintos de flujos hace que el sistema de E/S sea
mayor, ya que se necesitan dos jerarquas de clases. El nmero de clases de E/S hace que
el sistema parezca ms complejo de lo que en realidad es. Recuerde que, en la mayora
de los casos, la funcionalidad de los flujos de bytes es paralela a la de los de caracteres.
En el nivel inferior, toda la E/S sigue orientada a bytes. Los flujos de caracteres simple-
mente constituyen un medio cmodo y eficaz de procesar caracteres.
Java 7 ltll
Clases de flujo de bytes
Los flujos de bytes se definen con dos jerarquas de clases. En la parte superior hay
dos clases abstractas: InputStrearn y OutputStrearn. InputStrearndefine las caracte-
rsticas comunes de los flujos de entrada de bytes y OutputStrearn describe el compor-
tamiento de los flujos de salida de bytes.
A partir de InputStrearn y OutputStrearn se crean otras subclases concretas de
distinta funcionalidad y que se encargan de los detalles de leer y escribir en distintos
dispositivos, como archivos en disco. Las clases de fluj o de bytes se enumeran en la tabla
10.l. No se deje intimidar por la presencia de tantas clases. Cuando sepa usar un flujo
de bytes, podr dominar el resto.
Tabla 10.1. Clases de flujo de bytes.
Clase de flujo de bytes Significado
BufferedinputStream Flujo de entrada en bfer.
BufferedOutputStream Flujo de salida en bfer.
ByteArrayinputStream Flujo de entrada que lee desde una matriz de bytes.
ByteArrayOutputStream Flujo de salida que escribe en una matriz de bytes.
DatainputStream
DatautputStream
FileinputStream
FileOutputStream
FilterinputStream
FilterutputStrearn
InputStrearn
ObjectinputStrearn
ObjectutputStrearn
OutputStrearn
PipedinputStrearn
PipedutputStrearn
PrintStrearn
PushbackinputStrearn
SeguenceinputStream
Flujo de entrada que contiene mtodos para leer los tipos de
datos estndar de Java.
Flujo de salida que contiene mtodos para escribir los tipos de
datos estndar de Java.
Flujo de entrada que lee desde un archivo.
Flujo de salida que escribe en un archivo.
Implementa InputStrearn.
Implementa OutputStrearn.
Clase abstracta que describe flujos de entrada.
Flujo de entrada de objetos.
Flujo de salida para objetos.
Clase abstracta que describe el flujo de salida.
Conduccin de entrada.
Conduccin de salida.
Flujo de salida que contiene print () y println ().
Flujo de entrada que permite devolver bytes al flujo.
Flujo de entrada que combina dos o ms flujos de entrada que
se leen secuencialmente, uno tras otro.
1$tl 10. Utilizar E/S
Clases de flujo de caracteres
Los flujos de caracteres se definen mediante dos jerarquas de clases, en cuya parte
superior encontramos Reader y Writer, dos clases abstractas. Reader se usa para
entradas y Wri ter para salida. Las clases concretas derivadas de Reader y Wri ter
operan en flujos de caracteres Unicode.
A partir de Reader y Wri ter se derivan diversas clases concretas para controlar dife-
rentes situaciones de E/ S. Por lo general, las clases basadas en caracteres son paralelas a
las clases basadas en bytes. La tabla 10.2 resume las clases de flujo de caracteres.
Tabla 10.2. Clases de E/S de flujo de caracteres.
Clase de flujo de caracteres
BufferedReader
BufferedWriter
CharArrayReader
CharArrayWriter
FileReader
FileWriter
FilterReader
FilterWriter
InputStre arnReader
LineNurnberReader
OutputStrearnWriter
PipedReader
PipedWriter
PrintWriter
PushbackReader
Re ade r
StringReader
StringWriter
Writer
Significado
Flujo de caracteres de entrada en bfer.
Flujo de caracteres de salida en bfer.
Flujo de entrada que lee desde una matriz de carac-
teres.
Flujo de salida que escribe en una matriz de carac-
teres.
Flujo de entrada que lee desde un archivo.
Flujo de salida que escribe en un archivo.
Lector filtrado.
Escritor filtrado.
Flujo de entrada que traduce bytes en caracteres.
Flujo de entrada que cuenta lneas.
Flujo de salida que traduce caracteres en bytes.
Conduccin de entrada.
Conduccin de salida.
Flujo de salida que contiene print () y println () .
Flujo de caracteres que permite devolver caracteres al
flujo de entrada.
Clase abstracta que describe la entrada de flujo de
caracteres.
Flujo de entrada que lee desde una cadena.
Flujo de salida que escribe en una cadena.
Clase abstracta que describe la salida del flujo de carac-
teres.
Java 7 l!BI
Flujos predefinidos
Como ya sabe, todos los programas de Java importan automticamente el paquete
java . lang, que define la clase System, que encapsula distintos aspectos del entorno de
tiempo de ejecucin. Entre otros elementos, contiene tres variables de flujo predefinidas:
in, out y err. Estos campos se declaran como public, final y static en System,
lo que significa que se pueden usar en otras partes del programa y sin referencia a un
objeto System concreto.
System. out hace referencia al flujo de salida estndar. De forma predeterminada, es
la consola. System. in hace referencia a la entrada estndar, que de forma predetermi-
nada es el teclado. System. err hace referencia al flujo de error estndar, que tambin
es la consola de forma predeterminada. Sin embargo, estos flujos se pueden redirigir a
cualquier dispositivo compatible de E/S.
System. in es un objeto de tipo InputStream; System. out y System. err son
objetos de tipo PrintStream. Son flujos de bytes, aunque suelen usarse para leer y
escribir caracteres en y desde la consola. Son flujos de bytes y no de caracteres porque los
flujos predefinidos formaban parte de la especificacin original de Java, que no inclua
los flujos de caracteres. Como veremos despus, se pueden incluir en flujos basados en
caracteres si es necesario.
Utilizar los flujos de bytes
Comenzaremos el anlisis de la E/S de Java con los flujos de bytes. Como hemos
mencionado, en la parte superior de la jerarqua de flujos de bytes se encuentran las clases
InputStream y OutputStream. La tabla 10.3 muestra los mtodos de InputStream
y la tabla 10.4 los de OutputStream. Por lo general, los mtodos de InputStream y
OutputStream pueden generar IOException en caso de error. Los mtodos definidos
por estas dos clases abstractas estn disponibles para todas sus subclases. Por tanto,
forman un conjunto mnimo de funciones E/S presentes en todos los flujos de bytes.
Tabla 10.3. Mtodos definidos por lnputStream.
Mtodo
int available ()
void close ()
v o id mark ( int numBytes)
boolean markSupported ()
Descripcin
Devuelve el nmero de bytes de entrada disponibles para
lectura.
Cierra el origen de entrada. Los posteriores intentos de
lectura generan IOExcepti on.
Aade una marca al punto actual del flujo de entrada que
es vlida hasta que se lean numBytes .
Devuelve true si el flujo de invocacin admite mark ( ) /
res et ().
l!ti 10. Utilizar E/S
Mtodo
int read ()
int read (byte buffer [] )
int read (byte bf er [] ,
int desplazamiento,
int numBytes)
void re set ()
long skip (long numBytes)
Descripcin
Devuelve una representacin entera del siguiente byte
de entrada disponible. Devuelve - 1 al llegar al final del
flujo.
Intenta leer gasta los bytes de buffer. length en bfer
y devuelve el nmero real de bytes ledos correctamente.
Se devuelve -1 al llegar al final del flujo.
Intenta leer hasta los bytes de numBytes en bfer co-
menzando en bfer [desplazamiento] y devuelve el
nmero de bytes ledos correctamente. Devuelve - 1 al
llegar al final del flujo.
Restablece el puntero de entrada a la marca definida
previamente.
Ignora los bytes de entrada indicados por numBytes y
devuelve el nmero de bytes ignorados.
Tabla 10.4. Mtodos definidos por OutputStream.
Mtodo
void e lose ( )
void fl ush ()
void wr ite (int b)
void wri te (byte buffer [] )
void wri te (byte bfer [] ,
int desplazamiento,
int numBytes) miento].
Descripcin
Cierra el flujo de salida. Los posteriores intentos de
escritura generan IOException.
Enva a su destino la salida que se haya guardado en
bfer. Es decir, vaca el bfer de salida.
Escribe un solo byte en un flujo de salida. El parmetro es
int, lo que le permite invocar wri te ( ) con expresiones
sin tener que convertirlas de nuevo a byte.
Escribe una matriz completa de bytes en un flujo de
salida.
Escribe un subintervalo de numBytes bytes desde el
bfer de matriz, empezando por bfer [desplaza-
Leer entradas de consola
Originalmente, la nica forma de realizar entradas de consola consista en usar un flujo
de bytes y mucho cdigo de Java sigue utilizando exclusivamente flujos de bytes. En la
actualidad, puede usar flujos de bytes o de caracteres. En cdigo comercial, es preferible
usar un flujo orientado a caracteres, ya que facilita la internacionalizacin y el manteni-
miento de los programas. Tambin resulta ms cmodo operar directamente en caracteres
Java 7 ltllj
que tener que convertir entre caracteres y bytes. Sin embargo, en programas de ejemplo
para uso personal y aplicaciones que procesen entradas directas del teclado, se acepta
el uso de flujos de bytes. Por este motivo, veremos la E/S de consola con flujos de bytes.
Como System. in es una instancia de InputStream, tiene acceso automticamente a
los mtodos definidos por InputStream. Desafortunadamente, InputStream slo
define un mtodo de entrada, re ad (),que lee bytes. Hay tres versiones de re ad ():
int read() throws IOException
int read(byte datos[]) throws IOException
int read(byte datos[], int inicio, int max) throws IOException
En el captulo 3 vimos cmo usar la primera versin de re ad () para leer un carcter
desde el teclado (desde System. in). Devuelve -1 al alcanzar el final del flujo. La segunda
versin lee bytes desde el flujo de entrada y los aade a da tos hasta que la matriz se llene,
se alcance el final del flujo o se produzca un error. Devuelve el nmero de bytes ledos o
-1 al alcanzar el final del flujo. La tercera versin lee la entrada en datos comenzando
en la posicin indicada por inicio. Se almacena hasta max bytes. Devuelve el nmero
de bytes ledos o -1 al llegar al final del flujo. Se genera IOException en caso de error.
Al leer desde System. in, al pulsar Intro se genera una condicin de fin de flujo.
El siguiente programa muestra la lectura de una matriz de bytes desde System. in.
Las excepciones de E/S que se pueden generar se crea desde main ().Es un enfoque
habitual al leer desde la consola pero puede controlar este tipo de errores personalmente
si lo desea.
// Leer una matriz de bytes desde el teclado .
import java.io.*;
class ReadBytes {
public static void main(String args[J)
throws IOException {
byte data[] = new byte[lO];
System. out.println( " Enter sorne characters ." ) ;
System. in . read(data); /! leer una matriz de bytes desde el teclado
System. out . print( " You entered: ");
for(int i=O; i < data . length; i++)
System. out.print((char) data[i]);
Veamos un ejemplo:
Enter sorne characters .
Read Bytes
You entered: Read Bytes
Escribir salida en la consola
Como sucede con la entrada de consola, originalmente Java slo ofreca flujos de bytes
para salida. Java 1.1 aadi los flujos de caracteres. Para obtener cdigo ms portable, se
recomiendan flujos de caracteres. No obstante, como s ys tem. out es un flujo de bytes, se
1$1;j 10. Utilizar E/S
sigue utilizando salida de consola basada en bytes. De hecho, lo hemos utilizado en todos
los programas del libro vistos hasta ahora. La salida de consola se realiza con print ()
y prin tln (),que ya conoce. Estos mtodos se definen en la clase Prin tStream (el
tipo de objeto al que hace referencia System. out). Aunque Sys t e m. ou t es un flujo
de bytes, se puede usar para salida sencilla de consola. Como PrintStream es un flujo
de salida derivado de Ou tputStrea m, tambin implementa el mtodo de nivel inferior
wr i te () . Por tanto, se puede escribir en la consola por medio de wr i t e () . El formato
ms sencillo de wr i te () definido por Pr i ntSt.::::-ea m es el siguiente:
void write(int valorbyte)
Este mtodo escribe el byte especificado por v a lorb yte en el archivo. Aunque
valo r byte se declara como entero, slo se escriben los 8 bits de orden inferior. Veamos
un breve ejemplo que usa wri t e () para representar el carcter X seguido de una nueva
lnea:
11 Ejemplo de System. out . write( ).
class WriteDemo {
public static void main(String args[)) {
int b ;
b = ' X';
System. out . write(b); 11 escribir un byte en la pantalla
System. out . write( ' \n ' ) ;
No usar habitualmente wri te ( ) para salida de consola (aunque puede ser til en
determinados casos), ya que p r i n t ( ) y p r in t 1 n ( ) son ms fciles de usar.
Print St ream cuenta con otros dos mtodo de salida: print f () y f o r ma t ( ) .
Ambos le permiten controlar el formato preciso de los datos mostrados. Por ejemplo,
puede especificar el nmero de decimales, una anchura de campo mnima o el formato
de un valor negativo. Aunque no los usaremos en los ejemplos del libro, es aconsejable
que experimente con estas funciones de Java.
Leer y escribir archivos con flujos de bytes
Java le ofrece distintas clases y mtodos para leer y escribir archivos. Evidentemente,
los tipos ms comunes de archivos son los de disco. En Java, todos los archivos son orien-
tados a bytes y Java le ofrece mtodos para leer y escribir bytes desde y en un archivo.
Por tanto, la lectura y la escritura de archivos con flujo de bytes son operaciones habi-
tuales. No obstante, Java le permite incluir un flujo de archivo orientado a bytes en un
objeto basado en caracteres, como veremos ms adelante. Para crear un flujo de bytes
vinculado a un archivo, debe usar FileinputStream o Fi l eOutput St ream. Para
abrir un archivo, basta con crear un objeto de una de estas clases y especificar el nombre
del archivo como argumento del constructor. Una vez abierto el archivo, puede leer del
mismo o escribir en l.
Java 7 l!fl
Entradas desde un archivo
Un archivo se abre para entrada mediante la creacin de un objeto FileinputStre arn.
Veamos un constructor muy utilizado:
FileinputStream(String nombreArchivo) throws FileNotFoundException
Aqu, nornbreArc hi v o especifica el nombre del archivo que abrir. Si no existe se
genera FileNotFoundExce p tion, una subclase de I OExc eption.
Para leer desde un archivo puede usar read ().Usaremos la siguiente versin:
int read() throws IOException
Cada vez que se invoca, read ( ) lee un byte del archivo y lo devuelve como valor
entero. Devuelve -1 al llegar al final de archivo. Genera I OException en caso de
error. Por tanto, esta versin de read () es la misma que emplearnos para leer desde
la consola.
Cuando termine con un archivo, debe cerrarlo mediante la invocacin de close () ,
cuyo formato general se muestra a continuacin:
void close() throws IOException
Al cerrar un archivo se liberan los recursos del sistema asociados al mismo, que se
pueden usar en otro archivo diferente. Si se produce un fallo al cerrar un archivo, se
puede generar una fuga de memoria debido a la presencia de recursos sin utilizar.
El siguiente programa usa re a d () para aceptar y mostrar los contenidos de un archivo
de texto, cuyo nombre se especifica corno argumento de lnea de comandos. Los bloques
t ry / catch controlan los errores de E/S que se puedan producir.
/* Mostrar un archivo de texto .
*/
Para usar este programa , especifique el nombre
del archivo que desea ver .
Por ejemplo, para ver el archivo TEST . TXT,
use la sigui ente lnea de comandos .
java ShowFile TEST . TXT
import java . io .*;
class ShowFile {
public static void main(String args[] )
{
int i ;
FileinputStream fin ;
// Compr obar que se ha especificado un archivo .
if (args . length != 1) {
System. out . println (" Usage : ShowFi l e File" ) ;
return;
l!f:i 10. Utilizar E/S
try {
fin= new FileinputStream(args[O)) ;
catch(FileNotFoundException exc) {
System. out . println( " File Not Found" ) ;
return;
try {
11 leer bytes hasta final de archivo
do {
i = fin . read();
if(i != - 1) System. out . print((char) i) ;
while (i != - 1);
catch (IOException exc) {
System. out . println( "Error reading file ." ) ;
try {
fin . close() ; //cerrar el archivo
catch (IOException exc) {
System. out . println( "Error closing file ." ) ;
En el ejemplo anterior se cierra el flujo de archivos tras completarse el bloque t ry
que lee el archivo. Aunque es un enfoque til, Java admite una variante ms aconse-
jable. Consiste en invocar close () desde un bloque f i n ally. De esta forma, todos los
mtodos que acceden al archivo se incluyen en un bloque t r y y el bloque f inally se
usa para cerrar el archivo. De este modo, independientemente de cmo termine el bloque
try, el archivo se cierra. Siguiendo con el ejemplo anterior, veamos la nueva versin con
un bloque try para leer el archivo:
try {
do
i = fin.read() ;
if(i != - 1) System. out . print((char) i) ;
while (i ! = - 1) ;
catch(IOException exc)
System. out.println( " Error Reading File" );
finally {
11 Cerrar archivo al salir del bloque try
try {
fin . close();
catch(IOException exc) {
System. out . println( " Error Closing File" );
Una ventaja de este enfoque es que si el cdigo que accede al archivo termina por
una excepcin no relacionada con E/ S, el bloque f inal ly sigue cerrando el archivo.
Aunque en este ejemplo no sea un programa (o en otros muchos ejemplos), ya que el
programa termina si se produce una excepcin inesperada, puede llegar a ser proble-
mtico en programas de mayor tamao. Puede evitarlo con f inally.
Java 7 1$@
En ocasiones resulta ms sencillo incluir las partes de un programa que abren un
archivo y acceden al mismo en un mismo bloque try (en lugar de separarlas) y despus
usar un bloque f inal l y para cerrar el archivo. Por ejemplo, veamos otra forma de crear
el programa ShowFi l e :
1 * Esta variante contiene el cdigo que abre y
accede al archivo desde un mismo bloque try.
El archivo se cierra por el bloque finally .
*/
import java.io.*;
class ShowFile {
public static void main(String args[])
{
int i ;
FilelnputStream fin= null; // fin se inicializa en null
// Primero, confirmar que se ha especificado un nombre de archivo.
if(args.length != 1) {
System.out . println( " Usage : ShowFile filename " );
return;
11 El siguiente cdigo abre un archivo , lee caracteres hasta llegar al
11 final y cierra el archivo con un bloque finally .
try {
fin= new FilelnputStream(args[O]);
do
i = fin . read();
if(i != - 1) System. out . print((char) i);
while (i != - 1);
catch(FileNotFoundException exc) {
System. out . println( " File Not Found.");
catch(IOException exc) {
System. out . println( " An I/O Error Occurred" );
finally {
11 Cerrar archivo en todcs los casos.
try {
if(fin != null) fin . close() ; //cerrar fin slo si no es null
catch(IOException exc) {
System.out.println( " Error Closing File" ) ;
En este caso, se inicializa fin en null . Tras ello, en el bloque finally, el archivo
slo se cierra si f in no es nul l. Funciona porque f in no ser null slo si el archivo se
ha abierto correctamente. Por tanto, no se invoca c l ose () si se produce una excepcin
al abrir el archivo.
IM1i 10. Utilizar E/S
Tambin se puede compactar ms la secuencia try / c a t c h del ejemplo anterior. Como
Fi l e NotFoundExcept i on es una subclase de I OException, no es necesario captu-
rarla de forma independiente. Por ejemplo, la siguiente clusula catch se puede usar
para capturar ambas excepciones y no tener que capturar Fi leNotFoundException
de forma independiente. En este caso, se muestra el mensaje de excepcin estndar, que
describe el error.
catch(IOException exc) {
System. out.println( " I/0 Error: " + exc) ;
finally {
En este caso, los errores, incluidos los de apertura del archivo, se controlan con una
nica instruccin c a t ch. Al ser ms compacto, este enfoque se usa en la mayora de
ejemplos de E/S del libro. Recuerde, sin embargo, que no es adecuado cuando desea
procesar un fallo de apertura de archivo de forma independiente, como el provocado
si el usuario escribe incorrectamente el nombre de un archivo. En ese caso, tendra que
solicitar el nombre correcto, por ejemplo, antes de entrar en un bloque try que acceda
al archivo.
Preguntas al experto
P: He comprobado que r ead ( ) devuelve - 1 al llegar al final del archivo, pero que
carece de un valor especial para errores de archivo. Por qu?
R: En Java, los errores se controlan con excepciones. Por ello, si re a d ( ) u otro mtodo
de E/S devuelve un valor, significa que no se han producido errores. Resulta mucho
ms limpio que controlar errores de E/S mediante cdigos de error especiales.
Escribir en un archivo
Para abrir un archivo para salida, cree un objeto FileOutputSt r eam. Veamos dos
constructores muy utilizados:
FileOutputStream(String nombreArchivo) throws FileNotFoundException
FileOutputStream(String nombreArchivo, boolean append)
throws FileNotFoundException
Si el archivo no se puede crear, se genera FileNotFoundExcep tion. En el primer
caso, cuando se abre un archivo de salida, se destruyen los archivos ya existentes con el
mismo nombre. En el segundo, si append es true, se aade la salida al final del archivo.
En caso contrario, el archivo se sobrescribe.
Para escribir en un archivo, se usa el mtodo wr i te () , cuyo formato general es el
siguiente:
void write(int valbyte) throws IOException
Java 7 119-ji
Este mtodo escribe el byte especificado en v albyte en el archivo. Aunque v a lbyte
se declara como entero, slo se escriben en el archivo los 8 bits de orden inferior. Si se
produce un error de escritura, se genera IOException.
Cuando termine con la salida de un archivo, debe cerrarlo con c l ose ():
void close() throws IOException
Al cerrar un archivo se liberan los recursos del sistema asignados al mismo, para
poder usarlos en otro archivo. Tambin se garantiza que salida restante en un bfer de
disco se escriba en el disco.
El siguiente ejemplo copia un archivo de texto. Los nombres de los archivos de origen
y destino se especifican en la lnea de comandos.
/ * Copiar un archivo de texto .
* /
Para usar este programa, especifique el nombre
del archivo de origen y del archivo de destino .
Por ejemplo, para copiar el archivo FIRST.TXT
al archivo SECOND. TXT, use el s i g ~ i n t comando .
java CopyFile FIRST . TXT SECOND.TXT
import java.io.*;
class CopyFile {
public static void main(String arqs[)) throws IOException
{
int i ;
FileinputStream fin = null ;
FileOutputStream fout = null ;
//Primero comprobar que se han especificado los dos archivos.
if(args.length != 2) {
System. out . println( " Usage : CopyFile from to" );
return;
11 Copiar un archivo .
try {
11 Intentar abrir los archivos .
fin= new FileinputStream(args[O]) ;
fout = new FileOutputStream(args[l));
do
i = fin . read() ; 11 leer bytes de un archivo y escribirlos en otro
if(i ! = - 1) fout . write(i) ;
while (i != - 1) ;
catch(IOException exc)
System.out.println( " I/O Error : " + exc) ;
finally {
try {
if(fin != null) fin . close() ;
} catch(IOException exc) {
lf f I 10. Utilizar E/S
System.out . println( " Error Closing Input File" );
try {
if(fout != null) fout . close() ;
catch(IOException exc) {
System. out . println( " Error Closing Output File" ) ;
Cerrar automticamente un archivo
En el apartado anteriores, los programas realizaban invocaciones explcitas de
c l os e ( ) para cerrar un archivo cuando ya no era necesario. Es la forma de cerrar
archivos desde que se cre Java. Como resultado, es un enfoque habitual en cdigo exis-
tente, vlido y til. Pero el JDK 7 aade una nueva funcin que ofrece una nueva forma
racionalizada de gestionar recursos, como flujos de archivo, mediante la automatiza-
cin del proceso. Se basa en una nueva versin de la instruccin try denominada try
con recursos o administracin automtica de recursos. Su principal ventaja es que evita
situaciones en las que un archivo (u otro recurso) no se libera despus de que deje de
ser necesario. Como hemos mencionado, esto puede provocar fugas de memoria y otros
problemas. El formato general de la instruccin try con recursos es el siguiente:
try (especificacin-recurso)
// usar el recurso
Aqu, especificacin-recurso es una instruccin que declara e inicializa un
recurso, como un archivo. Se compone de la declaracin de una variable en la que la
variable se inicializa con una referencia al objeto gestionado. Al finalizar el bloque try,
el recurso se libera automticamente. En el caso de un archivo, significa que se cierra de
forma automtica. (Por tanto, no es necesario invocar close () de forma explcita.) Una
instruccin try con recursos tambin puede incluir clusulas catch y finally.
La instruccin try con recursos slo se puede usar con recursos que implementen
la interfaz AutoCloseable definida por java . lang. Esta interfaz, aadida en JDK
7, define el mtodo close (). AutoCloseable se hereda por la interfaz Closeable
definida en java. io. Ambas interfaces se implementan por las clases de flujos, como
FileinputStream y FileOutputStream. Por tanto, try con recursos se puede usar
para trabajar con flujos, incluidos los de archivos.
Como primer ejemplo de cierre automtico de un archivo, veamos una versin modi-
ficada del programa ShowFile:
/* Esta versin del programa ShowFile usa una instruccin try con recursos
para cerrar automticamente un archivo cuano deja de ser necesario.
Nota: Este cdigo requiere JDK 7 o posterior .
*/
java . io.*;
class ShowFile {
public static void main(String args[))
{
int i ;
// Primero comprobar que se especificado un nombre de archivo.
if (args. length ! = 1) {
System. out.println( " Usage : ShowFile filename " ) ;
return;
// El siguiente cdigo usa con recursos para abrir un archivo
// y despus cerrarlo automticamente al salir del bloque try.
try(FileinputStream fin= new FileinputStream(args[O])) {
do
i = fin . read () ;
if(i != - 1) System. out . print((char) i) ;
while (i != -1);
catch(IOException exc)
System. out . println( " I/0 Error: " + exc);
/ava l l'jl
En el programa, fjese especialmente en cmo se abre el archivo desde la instruccin
try con recursos:
try(FileinputStream fin= new FileinputStream(args[O))) {
La parte especifi cacin-recurso de try declara un FileinputStream con
el nombre fin, al que se asigna una referencia al archivo abierto por su constructor.
Tras ello, en esta versin del programa, la variable fin es local al bloque try, y se crea
al entrar en try. Al salir de try, el archivo asociado a fin se cierra automticamente
mediante la invocacin implcita de close (). No es necesario invocar close () de
forma explcita, lo que significa que no se puede olvidar de cerrar el archivo. Es una de
las principales ventajas de la administracin automtica de recursos.
Es importante entender que el recurso declarado en la instruccin try es fin al de
forma implcita, lo que significa que no puede asignar al recurso una vez creado. Adems,
el mbito del recurso se limita a la instruccin try con recursos.
Puede gestionar ms de un recurso en una misma instruccin try. Para ello, separe
la especificacin de cada recurso con punto y coma. En el siguiente programa puede ver
un ejemplo. Modifica el programa CopyFile anterior para que use una misma instruc-
cin try con recursos para gestionar fin y fout .
/* Una versin de CopyFile que usa try con recursos .
Muestra dos recursos (en este caso dos archivos) gestionados
por la misma instruccin try.
IJeji 10. Utilizar E/S
Nota : Este cdigo requiere JDK 7 o posterior .
*/
import java. io . *;
class CopyFile {
public static void main(String args[]) throws IOException
{
int i;
11 Confirmar primero que se han especificado ambos archivos .
if(args . length != 2) {
System. out . println( " Usage : CopyFile from to" ) ;
return;
11 Abrir y gestionar dos archivos a travs de la instruccin try.
try (FileinputStream fin new FileinputStream(args[O]) ;
FileOutputStream fout = new FileOutputStream(args[l] ))
do
i = fin . read() ;
if(i != - 1 ) fout . write ( i) ;
while (i ! = - 1) ;
catch(IOException exc )
System. out . println( " I/O Error : " + exc) ;
En el programa, fjese en cmo se abren los archivos de entrada y salida con t r y:
try (FileinputStream fin= new FileinputStream(args[O]) ;
FileutputStream fout = new FileOutputStream(args[l]))
Al finalizar este bloque t ry, se cierran tanto f i n como f out. Si compara esta versin
del programa con la anterior, comprobar que es mucho ms breve. La capacidad de racio-
nalizar el cdigo fuente es una ventaja adicional de las instrucciones try con recursos.
Debemos mencionar otro aspecto de t r y con recursos. Por lo general, al ejecutar
un bloque try, una excepcin interna puede generar otra que se produzca al cerrar el
recurso en una clusula f inally. En el caso de una instruccin try normal, la excep-
cin original se pierde y se cambia por la segunda. No obstante, en la instruccin try
con recursos, se suprime la segunda excepcin pero no se pierde. Se aade a la lista de
excepciones suprimidas asociada a la primera excepcin. Puede obtener la lista de excep-
ciones suprimidas con el mtodo getSuppr essed () definido por Throwable.
Debido a sus ventajas, se espera que try con recursos se use en cdigo nuevo, como
haremos en los restantes ejemplos del libro. No obstante, debe seguir familiarizado con
el enfoque tradicional de invocacin explcita de el ose (),por distintos motivos. Por un
lado, existen millones de lneas de cdigo de legado que recurren al enfoque tradicional.
Java 7 1 ~ j
Es importante que los programadores de Java conozcan y dominen este enfoque para
mantener o actualizar cdigo antiguo. Por otra parte, puede que tenga que trabajar en un
entorno que no use JDK 7. En ese caso, la instruccin t r y con recursos no estar dispo-
nible y deber usar el enfoque tradicional. Por ltimo, en determinados casos el cierre
explcito de un recurso puede ser ms apropiado que el enfoque automtico. Si utiliza
JDK 7 o posterior, seguramente use el nuevo enfoque de administracin de recursos por
ser una alternativa robusta y racionalizada del enfoque tradicional.
Leer y escribir datos binarios
Hasta ahora hemos ledo y escrito bytes con caracteres ASCII pero se pueden leer y
escribir otros tipos de datos. Por ejemplo, puede crear un archivo que contenga datos
int, double o shor t. Para leer y escribir valores binarios de tipos primitivos de Java
se usa Dat a inputStrearn y DataOutp u t St r earn.
Da taOutput St r earn implementa la interfaz Dat aOut put, que define mtodos
para escribir todos los tipos primitivos de Java en un archivo. Debe recordar que estos
datos se escriben con su formato binario interno, no en formato de texto legible para los
humanos. En la tabla 10.5 se muestran otros mtodos de salida muy utilizados con tipos
primitivos de Java. Todos generan IOExce ption en caso de fallo.
Tabla 10.5. Mtodos de salida ms utilizados definidos por DataOutputStream.
Mtodo de salida Funcin
void wri teBoolean (boolean val) Escribe el valor boolean especificado por val.
void wri teByte ( int val ) Escribe el orden de byte inferior especificado por
val.
void writeChar ( int val )
void wr i teDouble ( double val )
void writeFloat (float val)
void writeint ( int val)
void wri teLong (long val)
void wri t eShort (int val)
Escribe como char el valor especificado por val .
Escribe el valor doubl e especificado por val.
Escribe el valor float especificado por val.
Escribe el valor int especificado por val.
Escribe el valor long especificado por val.
Escribe como short el valor especificado por val.
A continuacin se muestra el constructor de Dat aOutputStrearn, que se basa en
una instancia de Ou t putSt rearn.
DataOutputStream(OutputStream flujoSalida)
Aqu, f 1 uj oSalida es el flujo en el que se escriben los datos. Para escribir salida en un
archivo, puede usar el objeto creado por Fi leOutputSt rearn para este parmetro.
IJei;j 10. Utilizar E/S
DatainputSt r eam implementa la interfaz Datai nput, que cuenta con mtodos
para leer todos los tipos primitivos de Java. En la tabla 10.6 se muestran dichos mtodos,
que pueden generar IOException.
Tabla 10.6. Mtodos de entrada ms utilizados definidos por DatalnputStream.
Mtodo de entrada Funcin
boolean readBoolean () Lee un valor boolean.
byte readByte () Lee un valor byte.
char readChar () Lee un valor char.
double readDouble () Lee un valor double.
float readFloat () Lee un valor float.
int readint ( ) Lee un valor int .
long readLong () Lee un valor long.
short readShort () Lee un valor short.
DatainputStream usa una instancia de InputStream como base, a la que aade
mtodos para leer los distintos tipos de datos de Java. Recuerde que DatainputStream
lee los datos en formato binario. A continuacin se muestra el constructor de
Datainpu tStream:
DatainputStream(InputStream flujoEntrada)
Aqu, fluj oEntrada es el flujo vinculado a la instancia creada de DatainputStream.
Para leer entradas desde un archivo, puede usar el objeto creado por Fi l einputStream
para este parmetro.
El siguiente programa ilustra el uso de Da taOutputStream y DatainputStream.
Escribe y despus lee distintos tipos de datos desde y en un archivo.
11 Escribir y leer datos binarios .
11 Este cdigo requiere JDK 7 o posterior.
import java.io.*;
class RWData {
public static void main(String args[])
{
int i = 10;
double d = 1023.56;
boolean b = true;
11 Escribir valores.
try (DataOutputStream dataOut =
new DataOutputStream(new FileOutputStream("testdata")))
System.out.println( "Writing " + i);
dataOut . writeint(i) ;
System.out.println( " Writing " + d) ;
dataOut.writeDouble(d);
System.out . println( " Writing " + b);
dataOut . writeBoolean(b);
System. out . println( "Writing " + 12.2 * 7.4);
data0ut.writeDouble(12 . 2 * 7.4);
catch(IOException exc) {
System. out . println( " Write error. " );
return;
System. out . println();
11 Ahora leerlos .
try (DatainputStream dataln =
new DatainputStream(new FileinputStream( " testdata" )))
i = datain . readint();
System. out . println( " Reading" + i);
d = datain.readDouble();
System.out.println( " Reading " + d);
b = dataln.readBoolean();
System. out . println( "Reading " + b);
d = datain . readDouble();
System.out.println ( " Reading " + d) ;
catch(IOException exc) {
System.out . println( " Read error. " );
Este programa genera el resultado mostrado en la figura 10.1.
ii Smbolo del sistema
Figura 10.1. Escritura y lectura de datos binarios.
Java 7 lffl
lfi:I 10. Utilizar E/S
Ejercicio 10.1. Utilidad de comparacin de archivos
Este ejercicio desarrolla una sencilla pero til utilidad de comparacin de archivos.
Abre los dos archivos a comparar y despus lee y compara para conjunto de bytes. Si
detecta una diferencia, los archivos son distintos. Si se llega simultneamente al final de
cada archivo y no hay diferencias, los archivos son iguales. Se utiliza la nueva instruc-
cin try con recursos para cerrar automticamente los archivos.
l. Cree un archivo con el nombre CompFiles . java.
2. En CompFiles . j ava, aada el siguiente programa:
/*
Ejercicio 10 . 1
Comparar dos archivos.
Para usar este programa , especifique los nombres
de los archivos que comparar en la lnea de comandos.
java CompFile FIRST.TXT SECOND.TXT
Este cdigo requiere JDK 7 o posterior.
*/
import java.io.*;
class CompFiles {
public static void main(String args[))
{
int i=O, j=O;
11 Comprobar primero que se han especificado los dos archivos .
if(args . length !=2 )
System.out.println( " Usage : CompFiles fl f2 " ) ;
return;
11 Comparar los archivos .
try (FileinputStream fl = new FileinputStream(args[O]) ;
FileinputStream f2 = new FilelnputStream(args[l)))
11 Comprobar el contenido de cad archivo .
do
i = fl . read () ;
j = f2 . read() ;
if(i != j) break;
while(i != -1 && j != - 1);
if (i != j)
System.out . println( " Files differ ." ) ;
el se
System.out . println( " Files are the same ." );
catch(IOException exc) {
Java 7 IJ9ji
System. out . println( "I /O Error : " + exc );
3. Para probar CompFiles, copie CompFiles. java a un archivo con el nombre
temp. Tras ello, pruebe esta lnea de comandos:
java CompFiles CompFiles . java temp
El programa indica que los archivos son iguales. Tras ello, compare
CompFiles. j ava con CopyFile. java (mostrado antes) con esta lnea de
comandos:
java CompFiles CompFiles . java CopyFile . java
Los archivos difieren, hecho que muestra CompFiles.
4. Como ejercicio personal, intente mejorar CompFiles con distintas opciones. Por
ejemplo, aada una opcin que ignore las maysculas y minsculas de las letras.
Tambin puede hacer que Com.pFiles muestre la posicin del archivo en la que
difiere con respecto al otro.
Archivos de acceso aleatorio
Hasta el momento hemos usado archivos secuenciales, a los que se accede de forma
lineal, un byte tras otro. Sin embargo, Java tambin le permite acceder a los contenidos
de un archivo de forma aleatoria. Para ello, se usa RandomAccessFile, que contiene
un archivo de acceso aleatorio. RandomAccessFile no se deriva de InputStream ni
OutputStream, sino que implementa las interfaces Datainput y DataOutput, que
definen los mtodos bsicos de E/S. Tambin admite solicitudes de posicin, es decir,
puede ubicar el puntero de archivo en el archivo. Usaremos el siguiente constructor:
RandomAccessFile(String nombreArchivo, String acceso)
throws Fi leNotFoundException
Aqu, el nombre del archivo se pasa en nombreArchi voy acceso determina el tipo
de acceso a archivo permitido. Si es
11
r
11
, el archivo se puede leer pero no escribir; si es
11
rw
11
, el archivo se abre en modo de lectura y escritura. El siguiente mtodo seek () se
usa para establecer la posicin actual del puntero de archivo:
void seek( long nuevaPos ) throws IOException
nuevaPos especifica la nueva posicin, en bytes, del puntero de archivo desde el
inicio del archivo. Tras invocar seek (),se produce la siguiente operacin de lectura o
escritura en la nueva posicin de archivo. RandomAccessFile implementa los mtodos
read () y wri te(). Tambin implementa las interfaces Datainput y DataOuput, por
lo que dispone de mtodos para leer y escribir los tipos primitivos, como readint ()
y wri teDouble ().
ltd1i 10. Utilizar E/S
El siguiente ejemplo ilustra la E/S de acceso aleatorio. Escribe seis valores double
en un archivo y despus los lee de forma no secuencial.
11 Ejemplo de archivos de acceso aleatorio.
11 Este cdigo requiere JDK 7 o posterior .
import java. io.*;
class RandomAccessDemo
public static void main(String args[])
{
double data[] = { 19 . 4, 10 . 1 , 123 . 54 , 33.0, 87.9, 74.25 ) ;
double d;
11 Abrir y usar un archivo de acceso aleatorio .
try (RandomAccessFile raf = new RandomAccessFile(
11
random. dat
11
,
11
rw
11
))
{
11 Escribir valores en el archivo .
for(int i=O; i < data.length; i++)
raf.writeDouble(data[i));
//Leer valores concretos
raf . seek(O); // buscar el primer double
d = raf . readDouble();
System. out.println(
11
First value is
11
+ d) ;
raf . seek(8); //buscar el segundo double
d = raf . readDouble();
System. out.println(
11
Second value is
11
+ d);
raf . seek(8 * 3); //buscar el cuarto d o ~ l e
d = raf . readDouble();
System.out.println(
11
Fourth value is
11
+ d);
System. out . println();
// Ahora leer valores alternos .
System. out . println(
11
Here is every other value :
11
);
for(int i=O; i < data.length; i+=2) {
raf . seek(8 * i) ; // buscar el ensimo double
d = raf . readDouble() ;
System.out . print(d +
11 11
);
catch(IOException exc) {
System. out . println(
11
I/O Error:
11
+ exc);
En la figura 10.2 puede ver el resultado generado por este.
Java 7 lnll
Figura 10.2. Resultado generado por el programa RandomAccessDemo.
Fjese en la posicin de cada valor. Como cada valor double tiene 8 bytes de longitud,
cada uno empieza en un lmite de 8 bytes. Por tanto, el primer valor se encuentra en
cero, el segundo empieza en el byte 8, el tercero en el byte 16, etc. As pues, para leer el
cuarto valor, el programa busca la posicin 24.
Preguntas al experto
P: Al consultar la documentacin del JDK, he visto la clase Console. se puede utilizar
para E/S basada en consola?
R: La respuesta breve es que s. La clase Console se aadi en el JDK 6 y se usa
para leer y escribir en la consola. Es una clase de utilidad, ya que gran parte de su
funcionalidad est disponible en System. in y System. out. No obstante, su uso
puede simplificar algunas interaccio.J11es de consola, en especial la lectura de cadenas.
Consol e no proporciona constructores, sino que se obtiene un objeto Console
mediante la invocacin de System. consol e (),tambin aadido en JDK 6. Se
muestra a continuacin.
static Console console()
Si hay una consola disponible, se devuelve una referencia a la misma. En caso
contrario, se devuelve null. Puede que no siempre haya una consola disponible,
como cuando se ejecuta un programa como tarea de fondo. Por tanto, si se devuelve
nul l, no se permite la E/S de consola. Console define varios mtodos de E/S
como readLine () y pri ntf (). Tambin define readPassword (), que se puede
usar para obtener una contrasea. Permite a su aplicacin leer una contrasea sin
mostrarla al escribirla. Tambin puede obtener una referencia a Rea de r y w rite r
conectados a la consola. Por lo general, Con sol e es una clase til para determinados
tipos de aplicaciones.
Utilizarlos flujos basados en caracteres de Java
Como hemos visto en apartados anteriores, los flujos de bytes de Java son potentes
y flexibles. Sin embargo, no son la forma idnea de procesar E/ S basada en caracteres.
Para ello, Java define las clases de flujo de caracteres. En la parte superior de la jerarqua
de flujos de caracteres se encuentran las clases abstractas Re ader y Wri ter. En la tabla
l!fj 10. Utilizar E/S
10.7 se muestran los mtodos de Rea der y en la tabla 10.8 los de Wri ter. La mayora de
estos mtodos genera I OException en caso de error. Los mtodos definidos por estas
dos clases abstractas estn disponibles para todas sus subclases. Por tanto, constituyen
un conjunto mnimo de funciones E/ S comunes a todos los flujos de caracteres.
Tabla 1O.7. Mtodos definidos por Reader.
Mtodo
abstract void close ()
vo id mark ( int numCarac)
boolean markSupported ()
int read ()
int read (char bfer [])
Descripcin
Cierra el flujo de entrada. Los posteriores intentos de
lectura generan IOException.
Aade una marca al punto actual del flujo de entrada
que es vlida hasta que se lean los caracteres indi-
cados por numCarac.
Devuelve true si el flujo admite mark ()/re set ( ).
Devuelve una representacin entera del siguiente
carcter disponible del flujo de entrada de invocacin.
Devuelve -1 al llegar al final del flujo.
Intenta leer hasta los caracteres indicados por
buffer . length en bfer y devuelve el nmero
real de caracteres ledos correctamente. Se devuelve
- 1 al llegar al final del flujo.
abstract int read (char bfer [ J , Intenta leer hasta los caracteres de numCarac en
int desplazamiento,
int numCarac )
int read (CharBuffer bfer)
boolean ready ()
void res et ()
long skip (long numCarac)
bfercomenzando en bfer [desplazamiento] y
devuelve el nmero de caracteres ledos correcta-
mente. Devuelve - 1 al llegar al final del flujo.
1 ntenta completar el bfer especificado por b fer y de-
vuelve el nmero de caracteres ledos correctamente.
Devuelve -1 al llegar al final del flujo. CharBuffer es
una clase que contiene una secuencia de caracteres,
como una cadena.
Devuelve true si la siguiente solicitud de entrada no
va a esperar. En caso contrario devuelve false.
Restablece el puntero de entrada a la marca definida
previamente.
Ignora los caracteres de entrada indicados por
numcarac y devuelve el nmero de caracteres ig-
norados.
Tabla 10.8. Mtodos definidos por Writer.
Mtodo
Wri ter append (charca)
Descripcin
Adjunta ca al final del flujo de salida de invocacin.
Devuelve una referencia al flujo de invocacin.
Wri ter append (CharSequence
carac)
Wri t er append (CharSequence
carac , int inicio, int fin)
abstract void close ()
abstract void flush ()
void wri te ( int ca)
void write (char bfer [] )
abstract void wri t e (char
bfer [] , int desplazamiento ,
int numCarac )
void write (Stri ng cadena)
void write (String cadena , int
desplazamiento , int numCarac)
Java 7 lid
Adjunta carac al final del flujo de salida de invo-
cacin. Devuelve una referencia al flujo de invoca-
cin. CharSequen ce es una interfaz que define
operaciones de slo lectura en una secuencia de
caracteres.
Aade la secuencia de carac que comienza en
inicio y termina en fin al final del flujo de salida de
invocacin. Devuelve una referencia al flujo de salida
de invocacin. CharSequence es una interfaz que
define operaciones de slo lectura en una secuencia
de caracteres.
Cierra el flujo de salida. Los posteriores intentos de
escritura generan IOException.
Enva a su destino la salida almacenada en bfer. Es
decir, vaca el bfer de salida.
Escribe un solo carcter en el flujo de salida de
invocacin. El parmetro es i nt , lo que le permite
invocar wri te () con expresiones sin necesidad de
volverlas a convertir a char.
Escribe una matriz completa de caracteres en el flujo
de salida de invocacin.
Escribe un subintervalo de n umC a r a c carac-
teres desde el bfer de matriz, empezando por
bfer [desplazamiento] , en el flujo de salida de
invocacin.
Escribe cadena en el flujo de salida de invocacin.
Escribe un subintervalo de numCarac caracteres de la
matriz cadena, comenzando en el desp lazamiento
especificado.
Entrada de consola con flujos de caracteres
Para la internacionalizacin de cdigo, la entrada desde la consola con los flujos de Java
basados en caracteres es una forma ms indicada de leer caracteres desde el teclado que
usar los flujos de bytes. Sin embargo, como Syste m. i n es un flujo de bytes, tendr que
incluir S ys tem. in dentro de alguna forma de Rea der. La clase ptima para leer entradas
de consola es Bu f f e r edReader, que admite un flujo de entrada en bfer. Sin embargo,
no puede crear BufferedReader directamente desde System. i n, sino que primero
debe convertirlo en un flujo de caracteres. Para ello, se usa Input St reamReader, que
convierte bytes en caracteres.
11$1 10. Utilizar E/S
Pai;a obtener un objeto InputStreamReader vinculado a System. in, use el
siguiente constructor:
InputStreamReader (InputStream flujoEnt rada)
Como System. in hace referencia a un objeto de tipo InputStream, se puede usar
como flujoEntrada.
Tras ello, con el objeto creado por InputStrearnReader, cree un Buf feredReader
con este constructor:
Buff eredReader(Reader l ectorEntrada )
Aqu, lectorEntrada es el flujo vinculado a la instancia creada de Buf f eredReader.
Si combinamos todos los elementos, la siguiente lnea de cdigo crea un BufferedReader
conectado al teclado.
Buff eredReader b r = new BufferedReader( new
I nputStreamReader(System. in) );
Tras ejecutar esta instruccin, br ser un flujo de entrada basado en caracteres vincu-
lado a la consola a travs de System. in.
Leer caracteres
Se pueden leer caracteres desde System. in con el mtodo read () definido por
BufferedReader como si se leyeran con flujos de bytes. Veamos las tres versiones de
re ad () admitidas por Buf feredReader.
int read( ) throws I OException
int read(char datos[]) throws IOException
int read(char datos[) , int inici o , int max) thr ows IOException
La primera versin de read () lee un carcter Unicode. Devuelve -1 al alcanzar el
final del flujo. La segunda versin lee los caracteres del flujo de entrada y los aade a
da tos hasta que se llene la matriz, se alcance el final del archivo o se produzca un error.
Devuelve el nmero de caracteres ledos o -1 al final de la matriz. La tercera versin lee
la entrada en datos comenzado por la posicin indicada por inicio. Se almacenan hasta
max caracteres. Devuelve el nmero de caracteres ledos o -1 al llegar al final del flujo.
Las tres generan IOException en caso de error. Al leer desde System. in, al pulsar
Intro se genera una condicin de fin de flujo.
El siguiente programa ilustra el uso de read () leyendo caracteres desde la consola
hasta que el usuario introduce un punto. Las excepciones de E/S que puedan generarse
provienen de main ().Como mencionamos antes, es un enfoque habitual al leer desde
la consola. Evidentemente, puede controlar estos errores mediante su programa.
11 Usar BufferedReader para leer caracteres desde l a consola .
import java . io . * ;
class ReadChars {
public static void main(String args[))
Java 7 IU,.j
throws IOException
char c;
BufferedReader br = new // crear BufferedReader vinculado a System.ini
BufferedReader(new InputStreamReader(System. in));
System.out.println( " Enter characters, period to quit ." ) ;
// leer caracteres
do
c = (char) br.read();
System. out.println(c);
while (c ! = ' . ' ) ;
En la figura 10.3 puede ver un ejemplo de ejecucin.
Figura 10.3. Lectura de caracteres desde la consola.
Leer cadenas
Para leer una cadena desde el teclado, use la versin de readLine ( ) que es miembro
de la clase Buf feredReader. Veamos su formato general:
String readLine() throws IOException
Devuelve un objeto String que contiene los caracteres ledos. Devuelve nul l si se
intenta leer al final del flujo.
El siguiente programa ilustra el uso de Buf feredReader y del mtodo readLine ( ).
Lee y muestra lneas de texto hasta que se introduce la palabra stop.
//Leer una cadena desde la consola con BufferedReader.
import java . io . *;
class ReadLines {
public static void main(String args[])
throws IOException
lldil 10. Utilizar E/S
11 crear BufferedReader con System. in
BufferedReader br = new BufferedReader(new
InputStreamReader(System. in)) ;
String str;
System. out . println ("Enter l ines of text ." ) ;
System. out.println( " Enter ' stop' to quit. " ) ;
do {
str = br.readLine();
System. out.println(str);
while(!str.equals( " stop" )) ;
Salida de consola con flujos de caracteres
Aunque en Java se pueda usar Systern. out para escribir en la consola, su uso se
recomienda especialmente para tareas de depuracin o programas de ejemplo corno los
del libro. En programas reales, es recomendable usar un flujo PrintWri ter. Es una de
las clases basadas en caracteres. Corno hemos indicado, al utilizar una clase basadas en
caracteres para salida de consola se facilita la internacionalizacin de un programa.
PrintWri ter define varios constructores. Utilizaremos el siguiente:
PrintWriter(OutputStream flujoSalida, boolean vaciarEnNuevaLinea)
Aqu, f luj oSalida es un objeto de tipo OutputStrearn yvaciarEnNuevaLinea
controla si Java vaca el flujo de salida en cada invocacin de p r in t 1 n () . Si
vaciarEnNuevaLinea es true, se vaca de forma automtica. Si es false, el vaciado
no es automtico. PrintWri ter admite los mtodos print () y println () de todos
los tipos incluido Obj e et. Por tanto, puede usar estos mtodos al igual que hemos hecho
con Systern. out. Si un argumento no es un tipo primitivo, los mtodos PrintWri ter
invocan el mtodo toString () del objeto y despus imprimen el resultado.
Para escribir en la consola con PrintWri ter, especifique Systern. out corno flujo
de salida y vace el flujo tras cada invocacin de println ().Por ejemplo, esta lnea de
cdigo crea un PrintWri ter conectado a la salida de consola:
PrintWriter pw = new PrintWriter(System.out, true);
La siguiente aplicacin ilustra el uso de PrintWri ter para controlar la salida de
consola:
11 Ejemplo de PrintWriter.
import java . io.*;
public class PrintWriterDemo
public static void main(String args[]) {
PrintWriter pw = new PrintWriter(System. out , true); //crear PrinterWriter
11 vinculado a System. out
int i = 10;
double d = 123 . 65;
pw.println( " Using a PrintWriter ." ) ;
pw.println(i);
pw.println(d) ;
pw.println(i + " + " + d + " is " + (i+d)) ;
Este programa genera el siguiente resultado:
sing a PrintWriter .
10
123 .65
10 + 123 . 65 is 133 . 65
Java 7 IUfl
Recuerde que puede usar S y s tem. out para escribir texto en la consola cuando
aprenda a usar Java o depure sus programas. Sin embargo, con Print Wri ter resulta
ms sencillo internacionalizar aplicaciones reales. Como en los programas de ejemplo el
uso de PrintWri ter no supone ventajas adicionales, seguiremos usando System. out
para escribir en la consola.
E/S de archivos con flujos de caracteres
Aunque el procesamiento de archivos orientado a bytes es el ms habitual tambin
puede usar flujos basados en caracteres para ello. La ventaja de los flujos de carac-
teres es que operan directamente en caracteres Unicode. Por ello, si desea almacenar
texto Unicode, los flujos de caracteres son sin duda su mejor opcin. Por lo general,
para realizar E/ S de archivos basada en caracteres, se usan las clases FileReader y
FileWri ter.
Utilizar FileWriter
FileWri ter crea un objeto Writer que puede usar para escribir en un archivo. Sus
constructores ms utilizados son los siguientes:
FileWriter(String nombreArchivo ) throws IOException
FileWriter(String nombreArchivo , b o ~ l e n append) throws IOException
Aqu, nombreArchi vo es el nombre de ruta completo de un archivo. Si append es
true, se aade la salida al final del archivo. En caso contrario, el archivo se sobrescribe.
En ambos casos se genera I OException en caso de fallo. FileWri ter se deriva de
Outpu tStreamWr i ter y Wri ter, por lo que tiene acceso a los mtodos definidos por
estas clases.
La siguiente utilidad de clave en disco lee lneas de texto introducidas desde el teclado
y las escribe en el archivo test . txt. Se lee texto hasta que el usuario introduce la palabra
stop. Se usa FileWri ter para salida en el archivo.
ltd:I 10. Utilizar E/S
11 Una sencilla utilidad de clave en disco para ilustrar.
11 Este cdigo requiere JDK 7 o posterior .
import java . io. * ;
class KtoD {
public static void main(String args[])
{
String str;
BufferedReader br =
new BufferedReader(
new InputStreamReader(System. in));
System. out . println("Enter text ( ' stop ' to quit) ." ) ;
try (FileWriter fw = new FileWriter( " test.txt '' )) //crear FileWriter
{
do
System.out . print( ": " );
str = br . readLine() ;
if (str. compareTo ("stop") == 0) brea<;
str = str + " \r\n"; // afiadir nueva linea
fw.write(str); //escribir cadenas en el archivo
while(str.compareTo( " stop" ) != 0);
catch(IOException exc) {
System. out . println("I/O Error: " + exc);
Utilizar FileReader
La clase FileReader crea un objeto Reader que puede usar para leer los contenidos
de un archivo. A continuacin vemos su constructor:
FileReader(String nombreArchivo) throws FileNotFoundException
nombreArchi vo es el nombre de ruta completo de un archivo. Genera FileNot
FoundException si el archivo no existe. FileReader se deriva de InputStreamReader
y Reader, por lo que tiene acceso a los mtodos definidos por estas clases.
El siguiente programa crea una sencilla utilidad de disco en pantalla que lee el archivo
test . txt y muestra sus contenidos en pantalla. Por tanto, es complementaria a la
utilidad del apartado anterior.
11 Una sencilla utilidad de disco en pantalla que ilustra FileReader .
11 Este cdigo requiere JDK 7 o posterior .
import java . io.*;
class Otos {
public static void main (String args []) {
String s;
// Crear y usar FileReader envuelto en BufferedReader .
Java 7 IIOOI
try (BufferedReader br = new BufferedReader(new FileReader( " test . txt")))
{
while((s = br.readLine()) != null) { / / leer lineas del archivo y
//mostrarlas en la pantalla
System.out . println(s);
catch(IOException exc) {
System. out . println( " I/O Error: " + exc);
En este ejemplo, FileReader se incluye en Buf f eredReader, lo que le permite
acceder a readLine ().Adems, br cierra automticamente el archivo.
Preguntas al experto
P: He odo hablar de otro paquete de E/S llamado NIO. Qu me puede decir al res-
pecto?
R: Llamado originalmente New I/O, NIO se aadi en el JDK i.4. Admite un enfoque
basado en canales a las operaciones de E/S. Las clases NIO se incluyen en java. nio
y sus paquetes subordinados, corno java. nio. channels y java. ni o . charset.
NIO se basa en dos elementos fundamentales: bfer y canales. Un bfer contiene
datos. Un canal representa una conexin abierta a un dispositivo de E/S, corno un
archivo o socket. Por lo general, para usar este sistema, se obtiene un canal a un
dispositivo de E/S y un bfer para guardar datos. Las operaciones de entrada y
salida de datos se realizan en el bfer.
Otras dos entidades usadas por NI o son los conjuntos de caracteres y los selectores.
Un conjunto de caracteres define la asignacin de bytes a caracteres. Puede codificar
una secuencia de caracteres en bytes por medio de un codificador y descodificar
una secuencia de bytes en caracteres con un descodificador. Un selector admite E/S
basada en claves, sin bloqueo y mltiple. Es decir, los selectores le permiten realizar
E/S a travs de varios canales. Los selectores suelen aplicarse a canales basados
en socket. Desde JDK 7, se ha mejorado NIO considerablemente y se suele usar
el trmino NI0.2. Las mejoras incluyen tres nuevos paquetes ( java . nio . file,
java . nio. file. attribute y java. nio. file. spi); nuevas clases, interfaces
y mtodos, y compatibilidad directa con E/S basada en flujos. Estas novedades han
ampliado los usos de NIO, en especial con archivos. Recuerde que NIO no sustituye
las clases de E/S de java. io, que veremos ms adelante, sino que las clases NIO
estn diseadas corno complemento del sistema E/S estndar, constituyendo un
enfoque alternativo muy til en determinadas circunstancias.
lf41i 10. Utilizar E/S
Utilizar envoltorios de tipos de Java
para convertir cadenas numricas
Antes de dejar el tema de E/S, veremos una tcnica muy til para leer cadenas num-
ricas. Como ya sabe, el mtodo println () de Java le permite representar distintos
tipos de datos en la consola, incluidos valores numricos de los tipos integrados, como
int y double. Por ello, println () convierte automticamente valores numricos a
un formato legible para los humanos. Sin embargo, mtodos como re ad () no cuentan
con la misma funcionalidad para leer y convertir una cadena con un valor numrico a
su formato binario interno. Por ejemplo, no existe una versin de read () que lea una
cadena como "1 O O" y despus la convierte automticamente a su correspondiente
valor binario que puede almacenar en una variable int. En su lugar, Java ofrece otras
formas de realizar esta tarea. Puede que la ms sencilla sea usar uno de los envoltorios
de tipos de Java.
Los envoltorios de tipos de Java son clases que contienen o envuelven tipos primitivos.
Son necesarios ya que los tipos primitivos no son objetos, lo que limita su aplicacin. Por
ejemplo, un tipo primitivo no se puede pasar por referencia. Para solucionar esta nece-
sidad, Java ofrece clases correspondientes a cada uno de los tipos primitivos.
Los envoltorios de tipos son Double, Float, Long, Integer, Short, Byte,
Character y Boolean. Estas clases ofrecen una amplia variedad de mtodos que le
permiten integrar los tipos primitivos en la jerarqua de objetos de Java. Como ventaja
adicional, los envoltorios numricos tambin definen mtodos que convierten una cadena
numrica en su correspondiente equivalente binario. En la tabla 10.9 vemos algunos de
estos mtodos de conversin. Cada uno devuelve un valor binario que se corresponde
a la cadena.
Envoltorio
Double
Float
Long
Integer
Short
Byte
Tabla 10.9. Mtodos de conversin.
Mtodo de conversin
static double parseDouble (String cadena) throws
NumberFormatException
static float parseFloat (String cadena) throws
NumberFormatException
static long parseLong (String cadena) throws
NumberFormatException
static int parseint (String cadena) throws
NumberFormatException
static short parseShort (String cadena) throws
NumberFormatException
static byte parseByte (String cadena) throws
NumberFormatException
Java 7 lfJI
Los envoltorios enteros tambin ofrecen otro mtodo de anlisis que le permite espe-
cificar la raz. Los mtodos de anlisis le permiten convertir un valor numrico, ledo
como cadena desde el teclado o un archivo de texto, a su formato interno adecuado. Por
ejemplo, el siguiente programa ilustra par seint () y parse Doub le ().Hace una media
de una lista de nmeros introducidos por el usuario. Primero pide al usuario el nmero
de valores que promediar. Trasello,leeelnmeroconreadLi ne () yusa parseint ()
para convertir la cadena en entero. Tras ello, muestra los valores, con parseDouble ( )
para convertir las cadenas a sus equivalentes double.
/* Este programa calcula la media de una lista de nmeros introducidos
por el usuario. */
import java . io . * ;
class AvgNums {
public static void main(String args[])
throws IOException
// crear BufferedReader con System.in
Buf f eredReader br = new
BufferedReader(new InputStreamReader(System. in)) ;
String str;
int n ;
double sum = O. O;
double avg, t;
System. out . print( " How many numbers will you enter: " );
str = br . readLine();
try {
n = Integer . parseint(strl ; 11 convertir cadena en int
catch(NumberFormatException exc)
System. out.println( " Invalid format") ;
n = O;
System.out . println( " Enter " + n + " values ." );
for (int i=O; i < n ; i++) {
System. out . print( " : " );
str = br.readLine();
try {
t = Double . parseDouble(str) ; 11 convertir cadena en double
catch(NumberFormatException exc) {
System.out . println( " Invalid format " );
t = O. O;
sum += t ;
avg = sum / n ;
System.out . println( "Average is " + avg);
En la figura 10.4 puede ver ejemplo.
lffj 10. Utilizar E/S
Figura 10.4. Resultado generado por el programa AvgNums.
Preguntas al experto
P: Para qu ms sirven las clases de envoltorio de tipos?
R: Los envoltorios de tipos primitivos ofrecen distintos mtodos que permiten integrar
los tipos primitivos en la jerarqua de objetos. Por ejemplo, algunos mecanismos
de almacenamiento de la biblioteca de Java, como mapas, listas y conjuntos, solo
funcionan con objetos. Por tanto, para almacenar un int en una lista, debe in-
cluirse en un objeto. Adems, todos los envoltorios de tipos cuentan con el mtodo
cornpareTo (), que compara el valor incluido en el envoltorio; equals (), que
prueba la igualdad de dos valores; y mtodos que devuelven el valor del objeto en
distintos formatos. En el captulo 12 encontrar ms informacin sobre los envol-
torios de tipos, cuando analicemos el autoboxing.
Ejercicio 10.2. Crear un sistema de ayuda basado en disco
En el ejercicio 4.1 creamos una clase He l p que mostraba informacin sobre las instruc-
ciones de control de Java. En esa implementacin, la informacin de la ayuda se alma-
cenaba en la propia clase y el usuario seleccionaba la ayuda entre un men de opciones
numeradas.
Aunque era un enfoque funcional no era la forma idnea de crear un sistema de
ayuda. Por ejemplo, para aadir o cambiar la informacin de ayuda, es necesario modi-
ficar el cdigo fuente del programa. Adems, la seleccin de un tema por nmero y no
por nombre resulta tediosa y es adecuada para extensas listas de temas. Aqu, remedia-
remos estos aspectos mediante la creacin de un sistema de ayuda basado en disco.
Este sistema de ayuda almacena la informacin en un archivo de ayuda, un archivo
de texto estndar que se puede cambiar o ampliar a voluntad, sin modificar el programa.
El usuario obtiene ayuda sobre un tema introduciendo su nombre. El sistema de ayuda
busca el tema en el archivo de ayuda. Si lo encuentra, se muestra la informacin sobre
el tema.
l. Cree el archivo de ayuda que se utilizar en el sistema de ayuda. Es un archivo
de texto estndar que se organiza de esta forma:
#nombre- temal
informacin del tema
#nombre- tema2
informacin del tema
#nombre-temaN
informacin del tema
Java 7 lfil
El nombre de cada tema debe precederse de un signo # y debe colocarse en una
lnea propia. De este modo, el programa puede buscar rpidamente el inicio de
cada tema. Tras el nombre del tema, se muestran varias lneas de informacin
sobre el mismo. Sin embargo, debe aparecer una lnea en blanco entre el final de
la informacin de un tema y el inicio del siguiente. Adems, no debe haber espa-
cios al final de las lneas.
A continuacin se muestra un archivo de ayuda que puede usar para probar el
sistema de ayuda basado en disco. Almacena informacin sobre las instrucciones
de control de Java.
#if
if(condition) statement;
else statement;
#switch
switch(expression)
case constant:
statement sequence
break;
/ / . ..
#for
for(init; condition; iteration) statement ;
#while
while(condition) statement ;
#do
do {
statement ;
) while (condition);
#break
break; or break label ;
#continue
continue; or continue label ;
Asigne el nombre h elpf ile . txt a este archivo.
2. Cree un archivo con el nombre FileHe lp. j a va.
,,,,
10. Utilizar E/S
3. Comience la creacin de la nueva clase Help con estas lneas.
class Help {
String helpfile ; // nombre del archivo de ayuda
Help(String fname) {
helpfi le = fname ;
El nombre del archivo de ayuda se pasa el constructor Help y se almacena en la
variable de instancia helpfile. Como cada instancia de Help tendr su propia
copia de helpf ile, cada instancia puede usar un archivo diferente. Por tanto,
puede crear distintos archivos de ayuda para diferentes temas.
4. Aada el mtodo helpo n () a la clase Help. Este mtodo recupera ayuda sobre
el tema especificado.
11 Mostrar ayuda sobre un tema .
boolean helpon(String what )
int ch;
String topic, info;
// Abrir e l archivo de ayuda .
try (BufferedReader helpRdr =
new BufferedReader(new FileReader(helpfile) ))
do {
11 leer caracteres hasta encontrar un smbolo #
ch = helpRdr . read() ;
// comprobar si los temas coinciden
if (ch == ' # ') {
topic = helpRdr . readLine() ;
if(what . compareTo(topic) == 0) { // tema encontrado
do {
info = helpRdr . readLine ( );
if(info ! = null) System.out.println (info) ;
while( (info != null) &&
(info. compareTo ( "" ) ! = O)) ;
return true ;
while(ch != - 1) ;
catch(IOException exc)
System. out.println( " Error accessing help file .") ;
return false ;
return false ; // tema no encontrado
Lo primero que mencionar es que he lpo n () controla todas las posibles excepciones
de E/S y no incluye una clusula throws . Al controlar sus propias excepciones,
evita que esta carga se pase al cdigo que lo usa. Por tanto, otro cdigo puede
invocar helpon () sin tener que incluir dicha invocacin en un bloque try / ca tch.
Java7 IUI
El archivo de ayuda se abre con FileReader que se incluye en Buf f eredReader.
Como el archivo de ayuda contiene texto, el uso de un flujo de caracteres permite
que el sistema de ayuda se pueda internacionalizar con mayor eficacia.
El mtodo he l p on ( ) funciona de esta forma. Una cadena con el nombre del tema
se pasa en el parmetro what. Tras ello, se abre el archivo de ayuda. Despus, se
busca en el archivo una coincidencia entre w ha t y un tema en el archivo. Recuerde
que en el archivo los temas se preceden de un smbolo #, por lo que el bucle de
bsqueda examina la presencia de # en el archivo. Si detecta uno, comprueba
que el tema que aparece detrs de ese smbolo# coincide con el pasado en what.
Si coincide, se muestra la informacin asociada a ese tema. Si se encuentra una
coincidencia, helpon () devuelve true. En caso contrario devuelve false.
5. La clase Help tambin cuenta con el mtodo getSelection (),que solicita al
usuario un tema y devuelve la cadena del tema introducida por el usuario.
// Obtener un tema de ayuda .
String getSelection() {
String topic =
llll.
'
BufferedReader br = new BufferedReader(
new InputStreamReader(System. in)) ;
System.out . print( " Enter topic: " ) ;
try {
topic = br . readLine() ;
catch(IOException exc) {
System. out . println (" Error reading console.");
return topic;
Este mtodo crea un BufferedReader conectado a System. in. Tras ello, soli-
cita el nombre de un tema, lee el tema y lo devuelve al invocador.
6. A continuacin se muestra el sistema completo de ayuda basado en disco:
/*
*/
Ejercicio 10 . 2
Un programa de ayuda que usa un archivo de disco
para almacenar informacin de ayuda.
Este cdigo requiere JDK 7 o posterior .
import java.io. *;
/* La clase Help abre un r c h i v ~ de ayuda ,
busca un tema y despus muestra la
informacin asociada a dicho tema .
Controla personalmente todas las excepciones
de E/S, sin necesidad de invocar cdigo
10. Utilizar E/S
para hacerlo . */
class Help {
String helpfile ; // nombre del archi10 de ayuda
Help(String fname) {
helpf i le = fname ;
11 Mostrar ayuda sobre e l tema .
boolean helpon(String what)
int ch;
String topic, info;
11 Abrir el archivo de ayuda .
try (BufferedReader helpRdr =
new BufferedReader(new FileReader(helpfile)))
do {
// leer caracteres hasta encontrar un smbolo #
ch= helpRdr.read() ;
11 comprobar si los temas coinciden
i f (ch == ' # ' ) {
topic = helpRdr . readLine();
if(what . compareTo(topic) == 0)
do {
info = helpRdr.readLine() ;
// tema encontrado
if(info ! = null) System. out . println(info) ;
while( ( info != null) &&
(info.compareTo ("" ) != 0)) ;
return true ;
while(ch != - 1) ;
catch(IOException exc)
System. out . println (" Error accessing help file ." ) ;
return false ;
return false ; // tema no encontrado
// Obtener un tema de ayuda .
String getSelection() {
String topic =
n".
,
BufferedReader br = new BufferedReader(
new InputStreamReader(System. in)) ;
System. out . print( " Enter topic : " ) ;
try {
topic = br . readLine() ;
catch ( IOException exc) {
System. out . println( " Error reading console .");
return topic ;
11 Ejemplo del sistema de ayuda basado en archivos .
class FileHelp {
public static void main (String args[]) {
Help hlpobj = new Help( "helpfile . txt " );
String topic;
Java 7 lkl
System. out . println( " Try the help system. " + " Enter ' stop ' to end ." ) ;
do
topic = hlpobj . getSelection() ;
if(!hlpobj . helpon(topic))
System.out . printl:i( " Topic not found.\n" ) ;
while (topic . compareTo( " stop") != 0 );
En la figura 10.5 puede ver un ejemplo.
Figura 10.5. Ejemplo del sistema de ayuda.
Preguntas al experto
P: Adems de los mtodos de anlisis definidos por los envoltorios de tipos primitivos,
existe otra forma sencilla de convertir una cadena numrica introducida desde el
teclado a su formato binario equivalente?
R: S. Otra forma de convertir una cadena numrica a su formato binario interno
consiste en usar uno de los mtodos definidos por la clase Sca nne r del paquete
java . util. Aadida en el JDK 5, Scanner lee entrada con formato (es decir,
legible para los humanos) y la convierte a formato binario. Scanner se puede
usar para leer entradas de distintas fuentes, como la consola o archivos. Por tanto,
lfl:I 10. Utilizar E/S
puede usar Scanner para leer una cadena numrica introducida desde el teclado y
asignar su valor a una variable. Aunque Sc a nner contenga demasiadas funciones
para describirlas en detalle, veamos su uso bsico. Para usar Scanner para leer
desde el teclado, primero debe crear un objeto Scanner vinculado a entradas de
consola. Para ello, use el siguiente constructor:
Scanner(InputStream desde)
Crea un objeto Scanner que usa el flujo especificad por desde como origen de la
entrada. Puede usar este constructor para crear un elemento Scanner vinculado
a la entrada de consola, como se indica a continuacin:
Scanner conin = new Scanner(System. in);
Funciona porque System. i n es un objeto de tipo Input Stream. Tras ejecutar esta
lnea, se puede usar con in para leer entradas desde el teclado. Tras crear Scanner,
basta con usarlo para leer entradas numricas. Veamos el procedimiento general:
l. Determine si un tipo concreto de entrada est disponible mediante la invocacin
de uno de los mtodos hasNe xtX de Scanner, donde X es el tipo de datos
deseado.
2. Si hay entrada disponible, se lee mediante la invocacin de uno de los mtodos
nextX de Scanne r.
Como se indica, Sca nner define dos grupos de mtodos que le permiten leer
entradas. Los primeros son los mtodos has Next , como hasNe xt int ( ) y
hasNextDouble ( ), por ejemplo. Estos mtodos has Next devuelven true si
el tipo de datos deseado es el siguiente elemento disponible en el flujo de datos
y f a l se en caso contrario. Por ejemplo, la invocacin de ha sNextint ( ) slo
devuelve true si el siguiente elemento del flujo es un entero en formato legible
para los humanos. Si los datos deseados estn disponibles, puede leerlos mediante
la invocacin de unos de los mtodos next de Sca nner, como nextint ( ) o
next Double ().Estos mtodos convierten la forma legible para los humanos de
los datos a su representacin binaria interna y devuelven el resultado. Por ejemplo,
para leer un entero, invoque next i nt ( ).La siguiente secuencia muestra cmo leer
un entero desde el teclado.
Scanner conin = new Scanner(System. in) ;
int i ;
if (conin . hasNextint()) i = conin.nextint();
Con este cdigo, si introduce el nmero 123 en el teclado, i contendr el valor 1 2 3.
Tcnicamente, puede invocar un mtodo next sin invocar primero un mtodo
hasNext . Sin embargo, no es aconsejable hacerlo. Si un mtodo next no puede
encontrar el tipo de datos que busca, genera InputMismatchException. Por este
motivo, conviene confirmar primero que el tipo de datos deseado est disponible
mediante la invocacin de un mtodo hasNext antes de invocar su correspondiente
mtodo next.
Java7 lfil
Evaluacin de conocimientos
l. Por qu define Java flujos de bytes y caracteres?
2. Aunque la entrada y salida de consola se basa en texto, por qu sigue utilizando
Java flujos de bytes para estos procesos?
3. Indique cmo abrir un archivo para leer bytes.
4. Indique cmo abrir un archivo para leer caracteres.
5. Indique cmo abrir un archivo para E/S de acceso aleatorio.
6. Cmo puede convertir una cadena numrica como
11
12 3 . 2 3
11
a su equivalente
binario?
7. Cree un programa que copie un archivo de texto. En el proceso, debe convertir
todos los espacios en guiones. Use las clases de archivo de flujo de bytes. Use el
enfoque tradicional para cerrar un archivo mediante la invocacin explcita de
close().
8. Modifique el programa de la pregunta anterior para que use las clases de flujos
de caracteres. En esta ocasin, use la instruccin try con recursos para cerrar
automticamente el archivo.
9. Qu tipo de flujo es System. in?
10. Qu devuelve el mtodo read () de InputStream al alcanzar el final del
flujo?
11. Qu tipo de flujo se usa para leer datos binarios?
12. Reader y Wri ter se encuentran en la parte superior de las jerarquas de clases
13. La instruccin t r y con recursos se usa para ___________ _
14. Si aplica el mtodo tradicional para cerrar un archivo, cerrarlo en un bloque
f inally suele ser un enfoque adecuado. Verdadero o falso?

S-ar putea să vă placă și