Anda di halaman 1dari 15

REPUBLICA BOLIVARIANA DE VENEZUELA

INSTITUTO UNIVERSITARIO POLITECNICO


SANTIAGO MARIO
EXTENSIN MATURN

Archivos en Java

AUTOR:
-

Maturn, Diciembre 2014.

Introduccin

Los flujos de datos son secuencias de bytes. Es decir, un conjunto de bytes


en un orden especfico que pueden representar cualquier cosa: texto, un archivo,
un objeto, una imagen. Bytes en general. Un flujo de dato sirve de puente entre la
fuente de datos y la aplicacin (por ejemplo, lectura de un archivo desde el disco
duro), o entre la aplicacin y el destino (escritura hacia un archivo del disco duro).
Los flujos surgen por la necesidad de las aplicaciones Java de interaccionar
con el exterior de dos posibles formas: generando salida a la consola del DOS, a
un fichero y capturando datos procedentes del teclado, de ficheros, de pginas
web, etc.

Flujos de entrada y salida

La E/S en java se basa en el concepto de flujo, que es una secuencia


ordenada de datos que tienen una fuente (flujos de entrada) o un destino (flujos de
salida). Las clases de E/S aslan a los programadores de los detalles especficos
del sistema de funcionamiento de la mquina, al tiempo que posibilitan el acceso a
recursos del sistema por medio de ficheros o archivos (files).
La entrada y salida en java se implementa en el paquete java.io y todo el
cdigo presentado en este captulo se importa, aunque no se incluya la
correspondiente sentencia import.

Las clases de E/S ms sencillas son las siguientes:


Entrada bsica: la clase InputStream
La clase abstracta InputStream declara los mtodos para leer datos desde una
fuente concreta y es la clasa base de la mayor parte de los flujos de entrada
en java.io. Soporta los mtodos siguientes:

int read() lee un slo byte de datos y los devuelve en el rango [0..255].
Devuelve -1 cuando se alcanza el final del flujo y no puede seguir leyendo
bytes.

int read(byte [] buf) lee un array de bytes hasta buf.length. Devuelve el


nmero de bytes leidos o -1 cuando se llega al final del flujo.

int read(byte [] buf, int off, int len) lee len bytes del flujo (o los que pueda)
y los coloca a partir de la posicin off del array.

long skip(long count) salta hasta count bytes de entrada o hasta el final
del flujo de entrada, devolviendo el nmero de bytes saltados.

int available() devuelve el nmero de bytes que estn disponibles para


leerse.

void close() cierra el flujo de entrada que abri el constructor no-arg,


liberando los recursos asociados a ese flujo. No es necesario invocar este
mtodo ya que el flujo se cierra cuando se destruye el objeto aunque es
conveniente hacerlo ya que vuelca el buffer sobre el disco.

Salida bsica: la clase OutputStream


La clase abstracta OutputStream es anloga a InputStream slo que proporciona
mtodos para manejar el flujo de salida. Los mtodos que incluye son:

void write(int b) escribe b como byte, que, aunque sea declarado


como int es transformado a byte. Esto es porque habitualmente es el
resultado de una operacin previa.

void write(byte [] buf) escribe un array de bytes.

void write(byte [] buf, int offset, int count) escribe un array buf de bytes,
empezando en la posicin offset y escribiendo count de ellos, deteniendose
antes si encuentra el final del array.

void flush() vacia el flujo de modo que los bytes que quedaran por escribir
son escritos.

void close() cierra el flujo de salida liberando los recursos asociados a ese
flujo.

A menos que se diga lo contrario estos mtodos


excepcin IOException si detectan algn error en el flujo de salida.

lanzan

una

Salida con formato: la clase PrintStream


La clase PrintStream proporciona utilidades para dar formato a la salida. Tiene
dos mtodos print y println que estn sobrecargados para los tipos primitivos,
objetos, cadenas y arrays de caracteres. La diferencia entre ambos mtodos est
en
que println aade
un
carcter
de
nueva
lnea.
Adems
el
mtodo println adems puede llamarse sin argumentos, produciendo una nueva
lnea.
System.out es una referencia a PrintStream. PrintStream proporciona dos
constructores, ambos con un primer argumento de tipo OutputStream cuya
diferencia est en un segundo argumento booleano que indica si debe vaciar el
flujo con cada carcter de nueva lnea.
Entrada y Salida de Tipos Primitivos: las
clases DataInputStream y DataOutputStream
Aunque leer y escribir bytes es til, a menudo es necesario transmitir datos de
tipos primitivos dentro de un flujo.

Las clases DataInputStream y DataOutputStream proporcionan mtodos para


la lectura y escritura de tipos primitivos de un modo independiente de la mquina.
Entrada y Salida con Ficheros: las
clases FileInputStream y FileOutputStream
Gran parte de la entrada y salida de los programas se realiza basndose en
ficheros y para ello java.io aporta dos clases. Una para ficheros de
entrada, FileInputStream, y otra para ficheros de salida,FileOutputStream. La
diferencia entre ficheros de entrada y de salida es fundamental, pues situaciones
como intentar leer de un fichero de salida o viceversa pueden generar en
errores. FileOutputStream crea un fichero, salvo que exista y sea de slo lectura.
Estas clases aportan tres constructores cada una, dependiendo de la
informacin aportada para identificar el fichero a abrir:

Un constructor que toma como argumento un String que es el nombre del


fichero que se va a abrir.

Un constructor que toma un objeto de tipo File que se refiere al fichero (ver
la clase File).

Un constructor que toma un objeto de tipo FileDescriptor, que constituye un


valor dependiente del sistema de ficheros y que describe un fichero abierto.
Flujos E/S Estndar

El programador puede utilizar para la E/S los tres flujos del sistema que estn
disponibles
como
campos
estticos
de
la
clase System: System.in, System.out y System.err:

static InputStream in flujo de entrada estndar para leer datos de tipo


carcter.

static OutputStream out flujo de salida estndar para escribir mensajes.

static OutputStream err flujo de salida estndar para escribir mensajes de


error.

Normalmente la entrada estndar est asociada al teclado, y tanto la salida


estndar como la salida de error estndar estn asociadas al monitor, pero esto se
puede cambiar, redirigindolas a ficheros. Tanto out como err son de

tipo PrintStream, por tanto los mensajes de salida normal, como los de error, son
mostrados utilizando los mtodos print de la clase PrintStream.

Creacin, lectura y escritura de flujos

Por mucho, los mtodos ms importantes de un Stream son Read y Write, para
leer y escribir bytes (que a final de cuentas es el principal propsito de un flujo).
Alternativamente existen BeginRead, EndRead, BeginWrite y EndWrite para leer y
escribir de forma asncrona, pero stos mtodos al final se basan en Read y Write,
respectivamente.
El siguiente ejemplo muestra la forma bsica de leer bytes, aunque de
momento no nos importa qu tipo de flujo tratamos ni cmo lo hemos obtenido.

0
1

Stream stream = ObtenerStreamDeAlgunaForma();

0
2

byte[] buffer;
int singleByte;

0
3
0
4
0
5

// leer en bloques de 1024 bytes

buffer = new byte[1024];


while (stream.Read(buffer, 0, 1024) > 0)
{
// hacer algo con buffer

0
6

0
7

// leer todo el flujo al mismo tiempo

0
8
0
9
1

buffer = new byte[stream.Length];


stream.Read(buffer, 0, buffer.Length);

// leer byte por byte

singleByte = stream.ReadByte();

while (singleByte != -1)

11

1
2

// hacer algo con el byte

1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
En las lneas 7 a 11, se leen bloques de 1024 bytes hasta que ya no haya ms
que leer: Stream.Read copia los bytes en el primer parmetro, y regresa el nmero
de bytes que faltan por leer. Esto es especialmente til cuando tratamos con flujos
muy grandes, de tal suerte que evitamos consumir nuestra memoria RAM. Las
lneas 14 y 15 muestran cmo leer todos los bytes de un jaln. Esto es
especialmente til cuando el flujo que queremos leer suele ser un tamao
relativamente pequeo. Y finalmente, las lneas 18 en adelante muestra cmo leer
byte por byte. Esta forma es la que menos memoria consume pero la ms
ineficiente.

Escribir bytes en un flujo es mucho ms sencillo.


1

Stream stream = ObtenerFlujoDeAlgunaForma();

2
3

byte[] buffer;

byte singleByte;

5
6
7

// escribir un bloque de 1024 bytes

buffer = ObtenerBufferDeAlgunLado();
stream.Write(buffer, 0, 1024);

8
9
1
0

// escribir un byte

singleByte = ObtenerAlgunByte();
stream.WriteByte(singleByte);

11
Los flujos se leen/escriben de forma secuencial. Por ello, cuando se leen o
escriben bytes, la posicin del flujo avanza el nmero de bytes ledos/escritos. As,
en nuestro ejemplo anterior, cada vez que leo 1024 bytes, el puntero del siguiente
byte aumenta en 1024 (especificado por la propiedad Position). Por supuesto, si
queremos saltarnos hasta una posicin en particular, podemos utilizar el mtodo
Seek. As, en el siguiente ejemplo:
1

Stream stream = ObtenerFlujoDeAlgunaForma();

stream.Seek(1024, SeekOrigin.Begin);

3
4

stream.Seek(1024, SeekOrigin.Current);
stream.Seek(1024, SeekOrigin.End);

Tenemos que en la lnea 2 nos movemos a la posicin 1024 desde el


principio. Luego nos movemos otros 1024 bytes desde la posicin actual, lo cul
nos ubicara en la posicin 2048. Y finalmente, la cuarta lnea nos ubica a 1024
bytes del final del flujo.
Es importante resaltar que un flujo puede ser de lectura y escritura, o de
solo lectura o de solo escritura. Eso lo podemos saber gracias a las propiedades
CanRead y CanWrite. Si violamos estas limitantes obtendremos una bonita
excepcin NotSupportedException. Por ejemplo, si abrimos un archivo en forma
de solo lectura e intentamos escribir en ella.

Cada tipo de flujo suele definir la forma ms eficiente para escribir en su


destino (por ejemplo un archivo). Usualmente crearn un bfer en la memoria y
solo cuando ste se llene lo escribirn en el destino. De esta forma, se hace ms
eficiente el proceso de escritura. Podemos, sin embargo, forzar a que el flujo
escriba en su fuente llamando al mtodo Flush.
Una vez que terminemos de utilizar un flujo, tenemos que cerrarlo con el
mtodo Close, o alternativamente llamando al mtodo Dispose (quien a su vez
llamar a Close). Esto es muy importante, porque de no hacerlo el flujo no liberar
los recursos que tenga asociados y stos permanecern en memoria hasta que
finalice la ejecucin de la aplicacin a la que pertenece, efectivamente causando
una fuga de memoria en el mejor de los casos, pudiendo bloquear recursos (como
archivos o conexiones de red) y hasta acabarse la memoria RAM, en el peor
escenario.
Una forma fcil de asegurarse que esto no pasa es utilizar la clusula
using como se muestra a continuacin:
1

Stream stream = ObtenerFlujoDeAlgunaForma();

using (stream)

3
4
5

{
// hacer algo con el flujo

} // se llama a Dispose de forma automtica

Archivos, directorios y rutas (File, Directory, Path)

Un archivo JAR (por sus siglas en ingls, Java ARchive) es un tipo de


archivo que permite ejecutar aplicaciones escritas en el lenguaje Java. Las siglas
estn deliberadamente escogidas para que coincidan con la palabra inglesa "jar"
(tarro). Los archivos JAR estn comprimidos con el formato ZIP y cambiada su
extensin a .jar. Existen tres operaciones bsicas con este tipo de archivos: ver
contenido, comprimir y descomprimir.
Un archivo es un conjunto de datos de largo variable identificado con un
nombre. Un nombre de archivo suele tener dos partes separadas por un punto. La
primera parte alude a su propsito; la segunda, llamada extensin, indica el tipo de
datos que contiene. Un archivo cuyo nombre termina en .class contiene la
definicin de una clase Java y el cdigo ejecutable para sus mtodos; un archivo

terminado en ".java" contiene el texto del cdigo fuente escrito por el programador.
Los archivos se agrupan en directorios (hoy en da denominados carpetas). Un
directorio es un conjunto de archivos guardados bajo un nombre comn, el nombre
del directorio. Un directorio puede estar dentro de otro directorio, llamado a veces
"directorio padre. Se forma as un rbol de directorios, una organizacin
jerrquica de directorios y subdirectorios contenidos en ellos, en varios niveles. La
lista ordenada de directorios que lleva desde la raz del rbol hasta un archivo
especfico se denomina una ruta o en ingls "path".

Serializacin de objetos

La serializacin de un objeto consiste en obtener una secuencia de bytes


que represente el estado de dicho objeto. Esta secuencia puede utilizarse de
varias maneras (puede enviarse a travs de la red, guardarse en un fichero para
su uso posterior, utilizarse para recomponer el objeto original, etc.).
Para que un objeto sea serializable basta con que implemente la
interfaz Serializable. Como la interfaz Serializable no tiene mtodos, es muy
sencillo implementarla, basta con un implements Serializable y nada ms. Por
ejemplo, la clase Datos siguiente es Serializable y java sabe perfectamente
enviarla o recibirla por red, a travs de socket o de rmi. Tambin java sabe
escribirla en un fichero o reconstruirla a partir del fichero.
1
2
3
4
5
6

public class Datos implements Serializable


{
public int a;
public String b;
public char c;
}

Si dentro de la clase hay atributos que son otras clases, stos a su vez
tambin deben ser Serializable. Con los tipos de java (String, Integer, etc.) no hay
problema porque lo son. Si ponemos como atributos nuestras propias clases,
stas a su vez deben implementar Serializable. Por ejemplo:
1
2
3
4
5
6
7

/* Esta clase es Serializable porque implementa Serializable y todos sus


* campos son Serializable, incluido "Datos f;"
*/
public class DatoGordo implements Serializable
{
public int d;
public Integer e;

8
9

Datos f;

Generacin de interfaz grafica

Llamamos Interfaz Grfica GUI (Graphical User Interface) al conjunto de


componentes grficos que posibilitan la interaccin entre el usuario y la aplicacin.
Es decir ventnas, botones, combos, listas, cajas de dilogo, campos de texto, etc.
Primero tenemos que disear la aplicacin,programarla y por ltimo los
eventos que se generan a medida que el usuario interactua con la Interfaz. Los
componentes son objetos de las clases que heredan de la clase base componente
como Button, List, TextField, TextArea, Label, etc.
En una GUI los componentes son contenidos en Contenedores o
containers. Un Containes es un objeto cuya clase hereda de Container(clase que a
su vez es subclase de Component) y tiene la responsabilidad de contener
Componentes.
Generalmente una GUI se monta sobre un Frame. Est sera el Container
principal que contendr a los componentes de la Interfaz Grfica, un Container
podra contener a otros containers.
Creacin, eliminacin y renombre de archivos
Creacin: Si queremos crear un fichero con Java usaremos el mtodo
creteNewFile que generar el fichero en el path que le indiquemos.
Si bien debemos de tener en cuenta que el "directorio base" donde creemos
el fichero debe de existir. Por ejemplo, en el caso de que creemos un fichero
indicando el path "c:tempejemplocodigoficheroTexto", los directorios temporal y
ejemplodecodigo deben de existir.
As instanciaremos el objeto File de la siguiente forma:
1. File fichero = new File ("c:\temp\ejemplodecodigo\fichero.txt");

o bien indicando el directorio y el fichero por separado:

1. File fichero = new File ("c:\temp\carlos","fichero.txt");

Debemos de tener cuidado en utilizar la doble barra para indicar el directorio ya


que cuando utilizamos la barra sola se asume que es una secuencia de escape
del estilo n b t...
Una vez creado el fichero simplemente bastar invocar el mtodo createNewFile
teniendo cuidado de que puede ser lanzada la excepcin IOException a si que
debemos de capturarla.
1. try {
2.

// A partir del objeto File creamos el fichero fsicamente

3.

if (fichero.createNewFile())

4.
5.
6.

System.out.println("El fichero se ha creado correctamente");


else
System.out.println("No ha podido ser creado el fichero");

7. } catch (IOException ioe) {


8.

ioe.printStackTrace();

9. }

El mtodo devolver true si ha podido crear el fichero y false si no ha podido


llevarlo a cabo.
Eliminacin: Borrar un fichero con Java es una actividad bastante sencilla, ya que
mediante la clase File, la cual nos abstrae de la manipulacin de ficheros, se nos
ofrece un mtodo para llevar a cabo tal cometido.
Lo primero que deberemos de hacer es instanciar una clase File. Para
instanciar esta clase deberemos de pasar al constructor el nombre del fichero
sobre el que queremos trabajar.

1. File fichero = new File("fichero.txt");

Para borrar el fichero deberemos de invocar el mtodo .delete() de la clase File.


En caso de que se pueda realizar el borrado del fichero, dicho mtodo devolver
true. En caso contrario devolver false. Es por ello que deberemos de controlar su
respuesta.
1. if (fichero.delete())
2.

System.out.println("El fichero ha sido borrado satisfactoriamente");

3. else
4.

System.out.println("El fichero no puede ser borrado");

Renombrar: Entre las muchas operativas que se pueden hacer sobre un fichero
tenemos el renombrado de un fichero. Para ello la librera de Java, Java IO, nos
ofrece un mtodo sobre la clase File.
Lo primero que tenemos que hacer es instanciar la clase File sobre el fichero
que queramos realizar el renombrado. Para ello utilizamos el constructor de la
clase File, como podemos ver en la siguiente lnea de cdigo:
1. File f1 = new File("fichero1.txt");

Lo siguiente ser instanciar una nueva clase File con el nombre del fichero que
queramos poner. Vemos la lnea de cdigo:
1. File f2 = new File("fichero2.txt");

Con las dos abstraciones de los ficheros solo nos quedar el ejecutar el
mtodo .renameTo(File) sobre el primer fichero. El mtodo .renameTo(File) recibe
como parmetro un objeto File con el nuevo nombre. El que nosotros hemos
llamado f2

1. boolean correcto = f1.renameTo(f2);

El mtodo .renameTo(File) devuelve un valor booleano indicando si se ha


podido realizar el renombrado, o no. A si que para finalizar validaremos la variable
booleana con el fin de dar informacin al usario.
1. if (correcto)
2.

System.out.println("El renombrado ha sido correcto");

3. else
4.

System.out.println("El renombrado no se ha podido realizar");

Conclusin
Los programas nos entregan informacin producto de las funciones que se
le han definido, esta debe provenir de alguna fuente de datos (discos, CD-RW,
memoria) y seguramente necesitaremos enviar esta informacin o datos hacia otro
lugar para mostrarla o almacenarla. Estos son los flujos (en ingls stream) de
informacin.
En JAVA, un flujo es un objeto que sirve de intermediario entre el origen y el
destino de los datos. Esto tiene la ventaja que el programa leer y escribir en el
flujo de informacin sin importar el origen o el destino (la pantalla, un archivo, la
memoria, Internet, etc.). Adems, tampoco va a tener relevancia el tipo de dato
que se encuentra en este objeto. Por otro lado, esto significa un nuevo nivel de
abstraccin pues al programa ya no le importa saber nada acerca del dispositivo
del cual vienen o al cual van los datos.

Anda mungkin juga menyukai