Escolar Documentos
Profissional Documentos
Cultura Documentos
Introducción
Desde el inicio del curso hemos realizado operaciones de entrada y salida en Java, desde leer
un carácter que un usuario introduce por teclado hasta utilizar los métodos System.out.print()
y System.out.println() para imprimir datos en pantalla, en este capítulo veremos con más
detenimiento como funciona la entrada salida utilizando para ello el paquete java.io.
Para entender como funcionan las distintas clases del paquete java.io deberemos antes
comprender algunos conceptos básicos.
Flujos: Un flujo es una abstracción de una entidad que produce o consume datos. Un flujo se
debe vincular a un dispositivo físico para que pueda realizar su labor (por ejemplo un flujo de
entrada a la consola para poder obtener datos que introduzca el usuario).
Una particularidad de los flujos en java es que todos utilizan los mismos métodos y que se
pueden aplicar las mismas clases independientemente del dispositivo al que esté conectado,
es decir una misma clase puede utilizarse tanto para leer de un fichero como para leer de
consola.
Otro concepto a tener en cuenta son los tipos de flujo, podemos diferenciar dos tipos, según el
tipo de datos que producen o consumen:
Como hemos visto, Java posee flujos ya definidos en la librería java.io, por ejemplo in para
flujo de entrada estándar, out para flujo de salida estándar y err como flujo de error estándar,
dichos flujos por defecto se encuentra vinculados al teclado in y a la consola tanto out como
err.
La clase File
Antes de abordar el uso de los flujos para entrada y salida veamos brevemente una clase de
utilidad como es la clase File.
La clase File permite representar un fichero mediante un objeto, pudiendo realizar así
operaciones sobre él como por ejemplo conocer si un fichero existe, su tamaño, etc…
String nombreFich="File.txt";
fichero=new File(nombreFich);
if (fichero.exists()){
System.out.println("El fichero existe");
}
else{
try{
fichero.createNewFile();
System.out.println("¡¡ El fichero se creó con éxito !!");
}
catch (IOException exc){
System.out.println("Hubo un problema");
}
}
¿Cómo lo realiza?
En primer momento se crea un objeto de tipo java.io.File utilizando para ello el nombre de
fichero almacenada en la variable String nombreFich.
Posteriormente llamando al método exists del objeto File comprobamos si el fichero existe
mediante el if inicial.
Si se cumple la condición de que exista lanzamos un mensaje a consola indicando que existe el
fichero.
Como podemos comprobar, el cuerpo del else contrala que en la operación de creación de
fichero no haya ningún problema, es decir que no se produzca una excepción de
entrada/salida (IOException) y en caso de producirse generamos un mensaje de error al
usuario.
Entrada/Salida Binaria mediante flujos de bytes
Cuando utilizamos flujos de bytes utilizaremos cadenas de bytes para leer/escribir utilizando el
flujo, en la parte superior de la jerarquía de clases de estos flujos se encuentran las clases
InputStream y OutputStream. Deberemos tener en cuenta que los métodos de estas clases
pueden generar una IOException en caso de que se dé un error de lectura o escritura.
Los flujos de Bytes tienen como clases padre las clase InputStream y OutputStream, las cuales
son clases abstractas.
InputStream define las características de las clases de entrada mientras que OutputStream
define las de las clases de salida.
Otras dos clases a destacar son DataInputStream y DataOutputStream que permiten leer y
escribir los tipos primitivos de java.
Todas las clases de E/S mediante caracteres tienen en su nombre Reader o Writer.
Al igual que las clases basadas en bytes generan en caso de erro una IOException.
Al igual que en las orientadas a bytes tenemos clases BufferedReader y BufferedReader que
implementan un buffer interno para mejorar el rendimiento.
Podemos usar estos flujos para crear nuevos objetos flujo de E/S.
Usar Flujos de Bytes
Para usar flujos de bytes utilizaresmo los métodos definidos por las clases InputStream y
OutputStream.
Los principales métodos son read, write y close, otros métodos disponibles además son :
Usar Flujos de caracteres
Como hemos determinado, en la salida de caracteres se utilizan las clases Reader y Writer.
Sin embargo estas clases no son las más utilizadas como veremos posteriormente.
Al comienzo Java no contemplaba la lectura/Escritura mediante caracteres, todo se realizaba
mediante flujo de bytes. Por ello surgieron las clases InputStreamReader e InputStreamWriter
que nos permiten leer y escribir basándonos en caracteres sobre flujos basados en bytes.
Para ello creamos un objeto de estas clases a partir de uno de tipo InputStream o
OutputStream. ¿ algo lioso? , pues sí que le vamos a hacer…
Veamos como leer un carácter por consola, para ello utilizaremos la clase BufferedReader.
Si miramos sus constructores, vemos que necesitamos un objeto de tipo Reader para poder
crear nuestro objeto, teniendo en cuenta que la consola (System.in en este caso) es un objeto
de tipo BufferedInputStream, no podemos crear nuestro objeto. :’(
Constructores de BufferedInputStream
public BufferedReader(Reader in, int sz)
import java.io.*;
char car = 0;
try{
car=(char) entrada.read();
try{
cad=entrada.readLine();
catch(IOException exc){
¿Como hemos visto hemos podido leer una cadena y un String mediante read y readLine,
como leeríamos el resto de tipos básicos?
Facil, aprovechamos las clases contenedoras Integer, Double…etc y llamamos a los métodos
parseInt…
int numero=0;
String cad="";
try{
cad=entrada.readLine();
numero=Integer.parseInt(cadena);
id: int
nombre: String
apellido1:String
apellido2:String
En dicha clase también se encuentra inplementado el método toString() que devuelve una
representación de String del objeto.
Facil, en 1 linea:
En un fichero podemos leer y escribir de la misma manera que lo hemos hecho con los flujos
de consola, tan solo deberemos utilizar las clases File adecuadas dependiendo de si queremos
escribir/leer caracteres o bytes.
Para leer de un fichero mediante caracteres deberemos utilizar FileReader, para crearlo la
manera más sencilla es usar uno de los siguientes dos constructores:
FileReader(File file)
FileReader(String fileName)
Sin embargo mediante esta clase tan solo podremos ir leyendo carácter a carácter lo cual
puede llegar a ser tedioso, en nuestro caso supongamos que almacenamos cada dato en una
línea.
¿Cómo leemos líneas enteras?, fácil creando un objeto BufferedReader a partir de nuestro
FileReader y leyendo de este, ya que esta clase nos ofrece el método readLine().
Veamos como quedaría nuestro ejemplo:
Para ello creamos un objeto FileReader y pasamos a utilizarlo, veámoslo con un ejemplo:
fichero=new File("Miguel_Car.txt");
try{
//Puedo poner el segundo parametro a true para usar un constructor que añada al fichero
fichsalida2=new FileWriter(fichero);
fichsalida2.write(Integer.toString(perso1.getId()));
fichsalida2.write("\n");
fichsalida2.write(perso1.getNombre());
fichsalida2.write("\n");
fichsalida2.write(perso1.getApellido1());
fichsalida2.write("\n");
fichsalida2.write(perso1.getApellido2());
fichsalida2.write("\n");
fichsalida2.close();
}
Lectura a fichero mediante Bytes
Para Realizar la lectura de un fichero mediante bytes , para ello si no deseo complicarme
demasiado la vida puedo escribir directamente los tipos primitivos mediante la clase
DataInputStream, que nos ofrece métodos específicos para cada tipo que deseemos leer.
Veamos un ejemplo:
FileInputStream fichEntrada;
DataInputStream leer;
File fichero =new File("Miguel.txt");
Persona perso1,perso2;
fichero=new File("Miguel.txt");
try{
fichEntrada=new FileInputStream(fichero);
leer=new DataInputStream(fichEntrada);
perso2=new Persona();
perso2.setId(leer.readInt());
perso2.setNombre(leer.readUTF());
perso2.setApellido1(leer.readUTF());
perso2.setApellido2(leer.readUTF());
leer.close();
fichEntrada.close();
System.out.println("Hemos leido mediante Bytes: +perso2.toString());
}
catch(IOException e){
System.out.println("Hubo un problema de E/S: "+e.getMessage());
}
Escritura a fichero mediante Bytes
Al igual que con la lectura de fichero utilizaremos la clase DataOutputStream que nos facilitará
bastante el trabajo.
Veamos un ejemplo:
fichero=new File("Miguel.txt");
try{
if (!fichero.exists()){
fichero.createNewFile();
}
// Voy a escribir los datos de una persona mediante escritura de Bytes.
fichSalida=new FileOutputStream(fichero);
escribir=new DataOutputStream(fichSalida);
escribir.writeInt(perso1.getId());
escribir.writeUTF(perso1.getNombre());
escribir.writeUTF(perso1.getApellido1());
escribir.writeUTF(perso1.getApellido2());
escribir.close();
System.out.println("Hemos escrito mediante Bytes:
"+escribir.size()+"Bytes");
fichSalida.close();
}
catch(IOException e){
System.out.println("Hubo un problema de E/S: "+e.getMessage());
}
Nota final: Apuntes aún sin finalizar, tan solo para poder verlo en clase.