Está en la página 1de 10

El Sistema de E/S de Java 

Manejo de flujos de entrada y salida 

En  JAVA los  datos de entrada y salidas se llaman flujos. También se le  conoce como Stream. 


Medio de comunicación. 

Se usan flujos en lugar de cadenas (Strings) ya que a diferencia de estos últimos, los flujos no 
sólo pueden manejar arreglos de caracteres sino cualquier tipo de datos como: strings, tipos 
primitivos y objetos. 

La palabra flujo encierra una gran importancia ya que implica la condición de movimiento. Los 
datos  pueden  fluir  desde  una  fuente  para  ser  consumidos  por  un  programa,  en  ese  caso  se 
habla  de  un  flujo  de  entrada.  Los  datos  también  pueden  fluir  desde  un  programa  hacia  una 
entidad externa (que puede ser incluso otro flujo), en ese caso se habla de un flujo de salida.  

Las clases más básicas de E/S en java, son InputStream  y  OutputStream  las cuales permiten 
la lectura y escritura de bytes.  Existen  dos clases más abstractas, Reader  y Writer  , las cuales 
son capaces de leer y escribir datos en un formato más primitivo. 

Todas  estas  clases  se  encuentran  en  el  paquete  java.io,  por  lo  que  al  principio  del  código 
fuente tendremos que escribir la sentencia 

import java.io.*; 

La entrada/salida estándar (normalmente el teclado y la pantalla, respectivamente) se definen 
mediante dos objetos que puede usar el programador sin tener que crear flujos específicos. 

La clase System tiene un miembro denominado in que es una instancia de la clase InputStream 
que representa al teclado o flujo de entrada estándar. Sin embrago, el miembro out de la clase 
System  es  un  objeto  de  la  clase  PrintStream,  que  imprime  texto  en  la  pantalla  (la  salida 
estándar). 

Para leer desde teclado solamente tenemos que llamar a la función readLine desde System.in.  

      try{ 

System.in.readLine(); 

     }catch (IOException ex) {  } 

Obligatoriamente, el proceso de lectura ha de estar en un bloque try..catch. 

Para imprimir en pantalla tenemos que llamar a la función print o printl  desde System.out.  
System.out.println("Número de bytes leídos "+numBytes); 

Manejo de archivos 

Organización de archivos: 

En general existen dos tipos de archivos: 

A. Archivos  Secuenciales.‐  En  este  caso  los  datos  se  almacenan  en  forma  consecutiva  y 
no es posible leer (recuerdan que significa esta operación) ningún registro (recuerdan 
la  nota  de  arriba)  directamente  es  decir  para  leer  el  registro  n,  se  deberá  recorrer  o 
accesar los n‐1 registros anteriores.  
B. Archivos Directos o Random.‐ Para este caso si se puede acceder o leer un renglón n 
cualquiera.  

Almacenamiento en archivos: 

A. Modo Texto: en este caso los datos son almacenados usando código ascii y por tanto 
son plenamente visibles usando cualquier editor.  
B. Modo Binario: en este caso los datos son almacenados en notación hexadecimal y por 
tanto se ocupa un editor binario para reconocerlos sin embargo un archivo binario es 
más compacto que un archivo texto.  

clase File 

Proporciona información acerca de los archivos, de sus atributos, de los directorios, etc.  

Constructores 

File(String path)  
File(String path, String name)  
File(File dir, String name)  
 
El parámetro path indica el camino hacia el directorio donde se encuentra el archivo, y name 
indica  el  nombre  del  archivo.  Los  métodos  más  importantes  que  describe  esta  clase  son  los 
siguientes:  

• String getName()  
• String getPath()  
• String getAbsolutePath()  
• boolean exists()  
• boolean canWrite()  
• boolean canRead  
• boolean isFile()  
• boolean isDirectory()  
• boolean isAbsolute()  
• long lastModified()  
• long length()  
• boolean mkdir()  
• boolean mkdirs()  
• boolean renameTo(File dest);  
• boolean delete()  
• String[] list()  
• String[] list(FilenameFilter filter)  

Ejemplo: 

Intanciar un File 

import java.io.File;

public class Demo1 {


public static void main(String[] args) {
//La clase File con la misma ruta y nombre del archivo.
File f1 = new File("\\temp\\archivo.dat");
File f2 = new File(File.separator + "temp" + File.separator +
"archivo.dat");
File f3 = new File("/temp/archivo.dat");

System.out.println("f1="+f1+", f2="+f2+", f3="+f3);


}
}

Creando un archivo vacio: 

• Para crear un archivo vacio utilizamos el método: createNewFile(); 
• Utilizaremos el bloque try/cath porque la operación puede lanzar un excepción 
IOException. 

import java.io.File;
import java.io.IOException;

public class Demo2 {


public static void main(String[] args) {
try {
File f = new File("archivo.dat");
f.createNewFile();
} catch (IOException e) {
System.out.println("Error para crear un archivo!");
e.printStackTrace();
}
}
}

Para obtener un listado de archivos y directorios debemos llamar el


método list().

import java.io.File;

public class Demo3 {


public static void main(String[] args) {
//Crea un objeto que representa el directorio actual
File dir = new File(System.getProperty("user.dir"));
//Crea un array con el contenido de todos los directorios
String[] stDir = dir.list();
//Iimprime en consola el array
for (int i = 0; i< stDir.length;i++)
System.out.println(stDir[i]);
}

Para crear un directorio use el método mkdir()

import java.io.File;

public class Demo4 {


public static void main(String[] args) {
File dir = new File("temp");
//Crea un directorio
dir.mkdir();
}
}

Visualizando el árbol de directorios

• exists() retorno tru o false si existe el directorio.


• isDirectory: retorna true si es directorio y false si es archivo
• getPath(): retorna la ruta del directorio.
• getName(): retorna el nombre del archivo.

import java.io.File;

public class Demo5 {


private File dir;
public Demo5(String directorio) {
dir = new File(directorio);
}
public boolean directorioExiste() {
return dir.exists();
}
public boolean esDirectorio() {
return dir.isDirectory();
}
public void imprimirContenido() {
String[] listDir = dir.list();
if (listDir.length == 0) {
System.out.println(dir.getPath() + " es un
directorio vacio!");
return;
}
for (int i = 0; i < listDir.length;i++) {
File f = new File(dir.getPath(),listDir[i]);
if (f.isDirectory()) {
imprimirContenido(f);
} else {
System.out.println(f.getPath() + " - " +
f.getName() + " es un archivo!");
}
}
}
private void imprimirContenido(File d) {
String[] listDir = d.list();
if (listDir.length == 0) {
System.out.println(d.getPath() + " es un
directorio vacio!");
return;
}
for (int i = 0; i < listDir.length;i++) {
File f = new File(d.getPath(),listDir[i]);
if (f.isDirectory()) {
imprimirContenido(f);
} else {
System.out.println(f.getPath() + " - "
+f.getName() + " es un archivo!");
}
}
}

public static void main(String[] args) {


String inicio;
if (args.length == 0)
inicio = System.getProperty("user.dir");
else
inicio = args[0];
Demo5 ad = new Demo5(inicio);
if (! ad.directorioExiste()) {
System.out.println(inicio + " es un directorio que
no existe!");
return;
} else if (!ad.esDirectorio()) {
System.out.println(inicio + " no es directorio!");
return;
}
ad.imprimirContenido();
}
}

Archivos Binarios 

  DataOutputStream(),   

  DataInputStream(), 

Para  leer  datos,  se  crea  un  objeto  de  la  clase  DataInputStream  vinculándolo  a  un  objeto 
FileInputStream para leer desde un archivo en disco denominado pedido.txt. 

FileInputStream fileIn=new FileInputStream("pedido.txt"); 
DataInputStream entrada=new DataInputStream(fileIn)); 
 
o en una sola línea 

DataInputStream entrada=new DataInputStream(new FileInputStream("pedido.txt")); 

La  clase  DataInputStream  define  diversos  métodos  readXXX  que  son  variaciones  del  método 
read de la clase base para leer datos de tipo primitivo 

Boolean readBoolean(); 
byte readByte(); 
int readUnsignedByte(); 
short readShort(); 
int readUnsignedShort(); 
char readChar(); 
int readInt(); 
String readLine(); 
long readLong(); 
float readFloat(); 
double readDouble(); 
 

//leer los datos del archive


DataInputStream f=new FileInputStream("pedido.txt")
DataInputStream entrada=new DataInputStream(f);
double precio;
int unidad;
String descripcion;
double total=0.0;

try {
//while(true){
while ((descripcion=entrada.readLine())!=null) {
//descripcion=entrada.readLine();
unidad=entrada.readInt();
entrada.readChar(); //lee el carácter tabulador
precio=entrada.readDouble();
System.out.println("has pedido "+unidad+" "+descripcion+" a
"+precio+" S/.");
total=total+unidad*precio;
}
System.out.println("Final del archivo");
}catch (EOFException e) {
System.out.println("Excepción cuando se alcanza el final del
archivo");
}
System.out.println("por un TOTAL de: "+total+" pts.");
entrada.close();
 

La  clase  DataOutputStream    es  útil  para  escribir  datos  del  tipo  primitivo  de  una  forma 
portable.  Se  crea  un  objeto  de  la  clase  DataOutputStream  vinculándolo  a  un  objeto 
FileOutputStream. 

FileOutputStream fileOut=new FileOutputStream("pedido.txt"); 
DataOutputStream salida=new DataOutputStream(fileOut)); 
 
o en una sola línea 

DataOutputStream salida=new DataOutputStream(new FileOutputStream("pedido.txt")); 

La clase DataOutputStream define diversos métodos writeXXX que son variaciones del método 
write de la clase base para escribir datos de tipo primitivo 

void writeBoolean(boolean v); 
void writeByte(int v); 
void writeBytes(String s); 
void writeShort(int v); 
void writeChars(String s); 
void writeChar(int v); 
void writeInt(int v); 
void writeLong(long v); 
void writeFloat(float v); 
void writeDouble(double v); 
 
Cuando se alcanza el final del archivo se produce una excepción del tipo EOFException. 

// escribe los datos


FileOutputStream f= new FileOutputStream("pedido.txt");
DataOutputStream salida=new DataOutputStream(f);
double[] precios={1350, 400, 890, 6200, 8730};
int[] unidades={5, 7, 12, 8, 30};
String[] descripciones={"paquetes de papel", "lápices", "bolígrafos",
"carteras", "mesas"};

for (int i=0; i<precios.length; i ++) {


salida.writeChars(descripciones[i]);
salida.writeChar('\n');
salida.writeInt(unidades[i]);
salida.writeChar('\t');
salida.writeDouble(precios[i]);
}
salida.close(); 

Archivos de Texto 

PrintWriter(),   
BufferedReader(), 
 
Para  leer  un  archivo  de  texto  se  debe  crear  un  objeto  de  la  clase  BufferedReader  para  la 
escritura, vinculado a un objeto FileReader      

FileReader  flujoL = new FileReader (arch);   

BufferedReader    lectura = new BufferedReader (flujoL); 

Utilizamos el método readLine( ).        String m = lectura.readLine(); 

 Se  crea  un  objeto  de  la  clase  PrintWriter  para  la  escritura,  vinculado  a  un  objeto 
FileOutputStream            

FileOutputStream  flujoE = new FileOutputStream(arch,true);   

// true indica que si existe el archivo al abrir el flujo agregue los datos al final 

PrintWriter  escritura = new PrintWriter(flujoE); 

El metodo para grabar es println( ).        escritura.println(“datos a grabar”); 

El final del archivo se detecta cuando la función readLine devuelve null. 

ELIMINAR  en archivo 
Eliminar  o  dar  de  baja  en  un  archivo  secuencial,  implica  tener  que  estar  procesando  dos 
archivos a la vez, el segundo de ellos es un archivo temporal, un algoritmo de eliminación física 
quedaría como: 

Procedimiento:

1.- Abrir el archivo original en modo lectura.

2.- Abrir un archivo llamado temporal en modo escritura.

3.- Iniciar un ciclo de lectura del archivo original.

3a.- Dentro del ciclo leer el primer registro.

3b.- Validar el registro si no es eliminable, se escribe al archivo temporal.

3c.- Fin de ciclo (cerrar el ciclo).

4.- Cerrar ambos archivos.

5.- eliminar el archivo original.

6.- renombrar el archivo temporal con el nombre de archivo original.

// Si tenemos los dos archivos creados


File file1 = new File("c:\archivo1.dat");
File file2 = new File("c:\temporal.dat");
// Para eliminar y renombrar
if (file1.exists()) {
file1.delete();
}
file2.renameTo(file1);

Una segunda técnica, consiste en agregar un campo de estado (status) al registro, es agregar 
un  campo  especial  llamado  status  que  puede  ser  de  tipo  char,  con  algunos  caracteres  de 
control  que  se  puedan  cargar  en  el  por  ejemplo  una  'a'  significa  que  esta  en  alta,  una  'b' 
significa que esta en baja, etc. 

Lo único que se tiene que hacer, es que cuando se agrega o manda el registro por primera vez 
a  disco,  mandarlo  cargado  el  campo  de  status  con  'a'  y  estar  validando  con  if  siempre  este 
campo  en  cualquier  proceso  de  búsqueda  o  condición  o  despliegue,  si  se  encuentra  cargado 
con 'b' entonces solo avisar al usuario que esta de baja dicho registro. 

MODIFICAR  un archivo 

Es un proceso similar a la eliminación, Se usan los dos archivos el original y el temporal y si el 
registro  es  el  buscado,  se  hace  la  operación  correspondiente  y  después  se  graba  en  el 
temporal. 
Archivos Directos o Random.‐ 

Se dice que un archivo es de acceso u organización directa cuando para acceder a un registro n 
cualesquiera no se tiene que pasar por los n‐1 registros anteriores. 

Es decir, un archivo de acceso directo tiene que tener sus registros o renglones de un tamaño 
fijo o predeterminado de antemano. 

En java archivos de acceso directo pertenecen a la clase RANDOMACCESSFILE. 

Un archivo de acceso directo permite posicionar el apuntador interno de registros, a cualquier 
registro  determinado  sin  necesidad  de  pasar  por  todos  los  registros  anteriores,  usando  las 
siguientes funciones. 

1. Se crea un objeto de tipo FILE que se usa como parámetro para crear el archivo de
tipo RANDOMACCESSFILE.
2. Se crea el archivo: RandomAccessFile archivo=new
RandomAccessFile(arch,"rw");
a. El primer parámetro o argumento en esta función es la unidad de disco y el
nombre del archivo.
b. El segundo parámetro o argumento es llamado modo y es una de los varios
modos que podemos usar.
Value Meaning
"r" Open for reading only. Invoking any of the write methods of the resulting 
object will cause an IOException to be thrown.  

"rw" Open for reading and writing. If the file does not already exist then an 
attempt will be made to create it.  

"rws" Open for reading and writing, as with "rw", and also require that every 
update to the file's content or metadata be written synchronously to the 
underlying storage device.  

"rwd" Open for reading and writing, as with "rw", and also require that every 
update to the file's content be written synchronously to the underlying 
storage device.  

3. Cuando se ha finalizado de escribir al archivo se debe cerrar : Archivo.close();

Recordar que un archivo directo tiene un tamaño de registro predefinido y es importante que 
dicho  tamaño  se  respete,  para  el  caso  de  las  variables  strings  dentro  del  código  se  deben 
ajustar a ‘n’ caracteres, si la string es mas corta que dicho tamaño se tendrá que ampliar con 
caracteres  en  blanco  "  ",  si  el  tamaño  es  mas  grande  la  string  se  tendrá  que  recortar  con  el 
método substring(). 

También  es  importante  recordar  que  java  grabara  cada  carácter  de  la  string  usando  dos(2) 
bites en disco, es decir si son 25 caracteres utilizara 50 para la string y 4 bytes por cada entero, 
es importante conocer el tamaño de registros grabados en disco porque esta información se 
usa ampliamente en los programas. 

Se recomienda que las claves sigan la secuencia 0,1,2,3,4,5..... 

Usando archivo.seek() es posible posicionarse en cualquier byte del archivo.  El formato usado 
seek() es:   

archivo.seek((long)(clave)* tamañoderegistro)); 

ELIMINACION a un archivo 

En  archivos  directos  no  se  puede  ni  se  debe  eliminar  físicamente  registros  de  los  archivos 
porque la clave del registro esta enlazada directamente a la posición que dicho registro tiene 
en disco y no seria muy conveniente estarle cambiando la matricula al alumno cada rato o el 
número de serie al auto, etc. 

Es  por  eso  que  se  emplea  la  técnica  de  incluir  un  campo  de  estado,  status  o  bandera  en  el 
registro y conforme se va cargando el registro y antes de mandarlo a disco se le agrega a dicho 
campo el carácter 'A' ‐‐>alta, así que cuando se quiera una baja solo se pondría dicho campo 
en  'B'  y  todos  los  programas  de  lectura,  búsqueda  y  filtros  deberán  revisar  esta  campo  de 
estado antes de hacer algo con el registro. 

También podría gustarte