Anda di halaman 1dari 33

{ Salida por pantalla: pathSeparator: ; pathSeparatorChar: ; separator: \ separatorChar: \ canRead():true canWrite():true canRead():true exists():true getAbsolutePath():C:\datos\Victor\Documentos\java \io\file\sub\prueba.txt getCanonicalPath():C:\datos\Victor\Documentos\jav a\io\file\sub\prueba.

txt getName():prueba.txt getParent():sub getPath():sub\prueba.txt hashCode():-2131944982 isAbsolute():false isDirectory():false isFile():true lastModified():868560320000 length():29 5.7.2 La clase FileDescriptor. public class java.io.FileDescriptor { // Atributos

public static final FileDescriptor in; // FD de la entrada estndar public static final FileDescriptor out; // FD de la salida estndar public static final FileDescriptor err; // FD de la salida de error // ConstructorLa Entrada/Salida en Java. public FileDescriptor(); // Mtodos public native void sync() throws SyncFailedException; // Este mtodo no // termina hasta que se vacen todos los buffers intermedios. public native boolean valid(); // true si el FD es vlido { Esta clase no debera utilizarse para instanciar objetos de la misma, sino que se suele utilizar algn mtodo que devuelve un objeto de la clase FileDescriptor.

Acceso a ficheros secuenciales.

Para acceder a datos almacenados en ficheros sin demasiadas pretensiones de formateo, y con acceso secuencial, puede utilizarse la clase FileInputStream que implementa los mtodos de la clase InputStream sin mayores funcionalidades. Para almacenar datos en un fichero, puede crearse un stream de salida mediante la clase ms simple que implementa los mtodos de la clase OutputStream: FileOutputStream Los constructores respectivos son: Fichero de entrada Fichero de salida FileInputStream(String nombre); FileOutputStream(String nombre); FileInputStream(File fichero); FileOutputStream(File fichero);

FileInputStream(FileDescriptor fd ); FileOutputStream(FileDescriptor fd ); FileOutputStream(FileDescriptor fd, boolean aadir ); Pueden crearse streams de entrada o salida sobre ficheros utilizando como parmetro en el constructor: Un String: con el nombre del fichero junto con el path.La Entrada/Salida en Java. Un objeto de la clase File: con el fichero a utilizar. Un objeto de la clase FileDescriptor: con el descriptor de fichero. Mtodos de lectura y escritura de bytes: FileInputStream FileOutputStream public native int read(); public native void write(int b); public int read(byte b[]) public void write(byte b[]) public int read(byte b[], int d, int l); public void write(byte b[], int d, int l); El puntero del fichero avanza segn el nmero de bytes ledos en cada operacin read(). En ficheros de entrada, puede utilizarse el mtodo public native long skip(long n) para saltar n bytes adelante. Ambas clases permiten obtener el Descriptor de Fichero (FD) asociado mediante el mtodo public final FileDescriptor getFD(), y cerrarlo mediante public native void close(). El siguiente ejemplo toma un fichero de entrada y convierte las maysculas a minsculas (siempre que est en cdigo ascii y nicamente los cdigos del 65 al 90):

import java.io.*; class Fichero1{ public static void main(String arg[]) { FileInputStream f; int letra; try { f = new FileInputStream("prueba.txt");La Entrada/Salida en Java. while ((letra=f.read())!=-1) { if ((letra>64) && (letra<91)) letra+=32; System.out.print((char)letra); f.close(); { } catch(FileNotFoundException e) { System.err.println("Fichero no encontrado"); { catch(IOException e) { System.err.println("ERROR"); { { { Si se pretende tratar con streams de caracteres en lugar de bytes, pueden utilizarse las nuevas clases equivalentes a FileInputStream y FileOutputStream: FileReader y FileWriter respectivamente. Cuyos constructores son: Fichero de entrada Fichero de salida

FileReader (String nombre); FileWriter(String nombre); FileReader(File fichero); FileWriter(File fichero); FileReader(FileDescriptor fd ); FileWriter(FileDescriptor fd ); FileWriter(FileDescriptor fd, boolean aadir); Los mtodos para leer y escribir caracteres son heredados de las superclases InputStreamReader y OutputStreamWriter y son:La Entrada/Salida en Java.

FileReader FileWriter public int read(); public void write(int b); public int read(char b[]) public void write(char b[]); public int read(char b[], int d, int l); public void write(char b[], int d, int l); public void write(String s); public void write(String s, int d, int l);

El siguiente ejemplo lee un fichero de caracteres y lo copia, tal cual, sobre un fichero de salida:

import java.io.*; class Fichero2 { public static void main(String[] args) { try { File fEntrada = new File("prueba.entrada"); File fSalida = new File("prueba.salida"); FileReader frEntrada = new FileReader(fEntrada); FileWriter fwSalida = new FileWriter(fSalida); int c;

while ((c = frEntrada.read()) != -1) { fwSalida.write(c); { frEntrada.close(); fwSalida.close(); } catch (FileNotFoundException e) { System.err.println("Fichero no encontrado"); { catch (IOException e) { System.err.println("Error de E/S"); { { {

El siguiente ejemplo lee lneas de texto escritas desde el teclado y va escribindolas en el fichero de salida prueba.salida hasta que se encuentra la marca de final de fichero ^Z.La Entrada/Salida en Java.

import java.io.*; class Fichero3 { public static void main(String[] args) { BufferedReader teclado; InputStreamReader inStream; inStream=new InputStreamReader(System.in); teclado = new BufferedReader(inStream);

File fSalida = new File("prueba.salida"); try { String s; FileWriter fwSalida = new FileWriter(fSalida); PrintWriter w = new PrintWriter(fwSalida); while ((s = teclado.readLine())!=null ) { w.println(s); { fwSalida.close(); inStream.close(); } catch (FileNotFoundException e) { System.err.println("Fichero no encontrado"); { catch (IOException e) { System.err.println("Error de E/S"); { { { System.in InputStream FileWriter InputStreamReader BufferedReader PrintWriter Fi le Strings

readLine() println()La Entrada/Salida en Java.

En este caso, se ha utilizado la clase BufferedReader envolviendo a la clase InputStreamReader porque aade el mtodo readLine(), muy conveniente para los propsitos del programa. Tambin se utiliza la clase PrintWriter envolviendo a la clase FileWriter para utilizar un mtodo de escritura de lnea completa como println().

La clase RandomAccessFile.

public class java.io.RandomAccessFile implements DataOutput, DataInput { // Constructores public RandomAccessFile(File fichero, String modo) throws IOException; public RandomAccessFile(String nomF, String modo) throws IOException // El modo del fichero puede ser r (lectura) o rw (lectura/escritura). // Mtodos public native void close() throws IOException; // Cierra el fichero y recursos public final FileDescriptor getFD() throws IOException; // Devuelve el FD public native long getFilePointer() throws IOException; // Devuelve la // posicin del puntero del fichero (distancia en bytes desde el principio) public native long length() throws IOException; // n de bytes del fichero public native int read() throws IOException; // Lee un byte del fichero public int read(byte b[]) throws IOException; public int read(byte b[], int desplaza, int longitud) throws IOException; public final boolean readBoolean() throws IOException;

public final byte readByte() throws IOException; public final char readChar() throws IOException; public final double readDouble() throws IOException; public final float readFloat() throws IOException; public final int readInt() throws IOException; public final String readLine() throws IOException: public final long readLong() throws IOException; public final short readShort() throws IOException; public final int readUnsignedByte() throws IOException; public final int readUnsignedShort() throws IOException; public final void readFully(byte b[]) throws IOException; public final void readFully (byte b[], int desplaza, int longitud) throws IOException; public final String readUTF() throws IOException; public native void seek(long posicin) throws IOException; // posiciona el // puntero del fichero directamente (en bytes) public int skipBytes(int n) throws IOException // Salta n bytesLa Entrada/Salida en Java. public native void write(int b) throws IOException; // Escribe un byte public void write(byte b[]) throws IOException; public void write(byte b[], int desplaza, int longitud) throws IOException; public final void WriteBoolean(boolean x) throws IOException; public final void WriteByte(int x) throws IOException; public final void WriteBytes(String x) throws IOException; public final void WriteChar(char x) throws IOException; public final void writeChars(String s) throws IOException public final void WriteDouble(double x) throws IOException

public final void WriteFloat(float x) throws IOException public final void WriteInt(int x) throws IOException public final void WriteLong(long x) throws IOException public final void WriteShort(int x) throws IOException public final void writeUTF(String str) throws IOException; {

Esta clase sirve para crear un objeto de acceso a un fichero de acceso directo a partir de un objeto de la clase File o, directamente, a partir de un String que contenga el nombre del fichero. Los constructores aceptan un segundo parmetro que indica el modo de apertura, pudiendo ser uno de los dos siguientes valores: r Apertura en modo lectura. rw Apertura en modo lectura/escritura.

Esta clase tiene dos mtodos para mover el puntero del fichero: seek(long posicin) posicionamiento absoluto en el byte indicado por el parmetro.

skipBytes(int n) posicionamiento relativo saltando n bytes.

La posicin actual (puntero del fichero) puede ser obtenida mediante el mtodo: getFilePointer().La Entrada/Salida en Java.

Acceso a ficheros aleatorios.

Los ficheros de acceso aleatorio o directo permiten situar el puntero del fichero en una posicin determinada sin tener que recorrer previamente el contenido del fichero como ocurre con los ficheros de acceso secuencial vistos anteriormente. Para trabajar con ficheros aleatorios, nicamente es necesaria la clase RandomAccessFile, que proporciona directamente (no heredados) todos los mtodos para leer y escribir datos del fichero (los indicados en las interfaces DataInput y DatoOutput). El siguiente programa solicita que le sea proporcionado el nombre de un fichero. Despus pregunta el byte a modificar, muestra su valor y solicita el nuevo valor. Este proceso se repite hasta pulsar ^Z (final de fichero).

import java.io.*; class Fichero4 { public static void main(String[] args) { BufferedReader teclado; InputStreamReader inStream; PrintWriter pantalla; String nombreFichero,posicin,b; RandomAccessFile fichero; inStream=new InputStreamReader(System.in); teclado = new BufferedReader(inStream); File f; long punteroF; try {

// PrintWriter con autoflush a true pantalla = new PrintWriter(System.out,true); pantalla.println("Nombre de fichero:"); nombreFichero=teclado.readLine(); f = new File(nombreFichero); // apertura del fichero en modo lectura/escrit. fichero = new RandomAccessFile(f,"rw"); pantalla.println("^Z para terminar"); pantalla.println("byte a examinar:"); while ((posicin = teclado.readLine())!=null ) { try { // buscar la posicin en el fichero. // Integer.parseInt() obtiene int a partir // de un String fichero.seek(Integer.parseInt(posicin)); // obtener el puntero del fichero punteroF=fichero.getFilePointer();La Entrada/Salida en Java. // leer y mostrar el byte en la posicin pantalla.println("Valor del byte = "+ fichero.readByte()); pantalla.println("Nuevo valor del byte:"); b=teclado.readLine(); // posicionar el puntero del fichero en // el lugar guardado anteriormente fichero.seek(punteroF); // escribir el nuevo valor del byte

fichero.writeByte(Integer.parseInt(b)); } catch(IOException e) { System.err.println("No existe ese byte."); { catch(NumberFormatException e) { System.err.println("error num."); { pantalla.println("byte a examinar:"); { teclado.close(); pantalla.close(); fichero.close(); } catch (IOException e) { System.err.println("Error de E/S"); { { { System.in InputStream OutputStream InputStreamReader BufferedReader PrintWriter RandomAccessFile readLine() Datos System.out

readByte() writeByte() A la hora de modificar un byte en el fichero de acceso directo, hay que tener en cuenta que primero se lee el byte mediante readByte(). Este mtodo, adems deLa Entrada/Salida en Java. realizar la lectura, avanza el puntero de fichero un byte adelante, por lo que antes de realizar la escritura con writeByte(), habr que retrocederlo 1 byte. Tambin puede realizarse este proceso de la forma en que se ha hecho en el ejemplo; guardando la posicin del puntero del fichero mediante getFilePointer() antes de realizar la lectura y restaurndolo mediante seek() antes de escribir.

Serializacin de objetos.

De todos es conocida la importancia de poder salvar en memoria secundaria y permanente determinados estados o valores de una aplicacin en un momento determinado para ser restablecidos en algn momento posterior. Si un programador desea guardar permanentemente el estado de un objeto puede utilizar las clases vistas hasta el momento para ir almacenando todos los valores de los atributos como valores char, int, byte, etc. Pero esto puede ser muy molesto y complicado, ya que un objeto puede tener atributos que sean otros objetos, que a su vez tengan atributos que hagan referencia a otras clases y as sucesivamente. Pero existe una forma ms cmoda de enviar objetos a travs de un stream como una secuencia de bytes para ser almacenados en disco, y tambin para reconstruir objetos a partir de streams de entrada de bytes. Esto puede conseguirse mediante la serializacin de objetos.

La serializacin consiste en la transformacin de un objeto Java en una secuencia de bytes para ser enviados a un stream. Mediante este mecanismo pueden almacenarse objetos en ficheros o incluso en bases de datos como BLOBs (Binary Large OBject), o se pueden enviar a travs de sockets, en aplicaciones cliente/servidor de un equipo a otro, por ejemplo. Pero todo esto no es nuevo, ya poda hacerse antes de la serializacin de objetos, lo que ocurre es que con este instrumento se consigue de una forma mucho ms cmoda y sencilla.La Entrada/Salida en Java.

Esquema de funcionamiento de la serializacin.

Objeto Serializable alguna subclase de OutputStream Stream alguna subclase de InputStream ObjectOutputStream ObjectInputStream Tipos de datos s imp l e s writeXXX() writeObject() Objeto Serializable Tipos de datos s imp l e s

readXXX() readObject() Para enviar y recibir objetos serializados a travs de un stream se utilizan las clases java.io.ObjectOutputStream para la salida y java.io.ObjectInputStream para la entrada. La clase ObjectOutputStream necesita como parmetro en su constructor un objeto de la clase OutputStream (alguna de sus subclases, ya que OutputStream es abstracta): public ObjectOutputStream(OutputStream out) throws IOException; Si, por ejemplo, se utiliza como parmetro un objeto de la clase FileOutputStream, los objetos serializados a travs de este stream sern dirigidos a un fichero. La clase ObjectInputStream necesita como parmetro en su constructor un objeto de la clase InputStream (alguna de sus subclases, ya que IutputStream es abstracta):La Entrada/Salida en Java. public ObjectInputStream(InputStream in) throws IOException, StreamCorruptedException; Si, por ejemplo, se utiliza como parmetro un objeto de la clase FileInputStream, los objetos se deserializan despus de obtenerlos a travs de este stream que, a su vez, obtiene los bytes de un fichero.

Objetos serializables.

Slo los objetos de clases que implementen la interface java.io.Serializable o java.io.Externalizable o aquellos que pertenezcan a subclases de clases serializables pueden ser serializados.

En este captulo nicamente van a estudiarse los objetos serializables mediante la interface Serializable, que es ms sencilla porque automatiza el proceso. Los objetos que implementan la interface Externalizable deben encargarse de crear el formato en el que se almacenarn los bytes. La interface Serializable no posee ningn mtodo. Slo sirve para marcar las clases que pueden ser serializadas. Cuando un objeto es serializado, tambin lo son todos los objetos alcanzables desde ste (los atributos que son objetos), ignorndose todos los atributos static , transient y los no serializables. No se almacenan los valores de los atributos static porque stos pertenecen a la clase (no al objeto), y son compartidos por todos los objetos implementados a partir de sta. Tampoco se almacenan los atributos transient porque esta palabra reservada se utiliza precisamente para eso, para no formar parte de las caractersticas permanentes de los objetos. ! public class Persona implements java.io.Serializable{ // Esta clase debe ser Serializable para // poder ser escrita en un stream de objetos private String nombre; private int edad;La Entrada/Salida en Java. public Persona(String s, int i) { nombre=s; edad=i; { public String toString() { return nombre+":"+edad;

{ { Como puede comprobarse en el ejemplo anterior, en el fichero Persona.java, se ha declarado la clase Persona de forma que implemente la interface Serializable para poder ser serializada.

Escritura.

Para serializar objetos (tambin vectores y Strings) y escribirlos a travs del stream de salida se llama al mtodo writeObject() del objeto ObjectOutputStream creado: public final void writeObject(Object objeto) throws IOException; Tambin pueden escribirse, adems de objetos, valores de tipos de datos simples mediante cualquiera de los mtodos de la interface DataOutput, que implementa la clase ObjectOutputStream; write(int b); writeChars(String x); write(byte b[]); writeDouble(double x); write(byte b[], int desplaza, int longitud); writeFloat(float x); writeBoolean(boolean x); writeInt(int x); writeByte(int x); writeLong(long x); writeBytes(String x); writeShort(int x); writeChar(int x); writeUTF(String x); Todos estos mtodos generan excepciones de la clase IOException.

En realidad, la clase ObjectOutputStream no implementa la interface DataOutput, sino la interface ObjectOutput, que es una subinterface de DataOutput, por lo que hereda sus mtodos.La Entrada/Salida en Java. Veamos un ejemplo en el que se crea un stream de salida, en el cual se escribirn: un objeto de la clase Persona ($ visto en el punto anterior), un objeto de la clase fecha (Date) y un entero:

import java.io.*; import java.util.Date; class SerialEscribe { public static void main(String arg[]) { try { // Un OutputStream subyacente sobre el que // escribir los bytes FileOutputStream f=new FileOutputStream("prueba.dat"); // El objeto serializador ObjectOutputStream ost = new ObjectOutputStream(f); Persona persona=new Persona("Victor",30); Date fecha = new Date(); ost.writeObject(persona); ost.writeObject(fecha); ost.writeInt(13); ost.flush(); // vaciar el buffer ost.close(); } catch (IOException e) {

System.err.println(e); { { { En el caso de los objetos persona y fecha se utiliza el mtodo writeObject(), y pueden ser serializados porque tanto la clase Persona como la clase Date implementan la interface Serializable; y en el caso del literal entero 13, se utiliza el mtodo writeInt().

Lectura.

Para deserializar objetos despus de leerlos a travs del stream de entrada se llama al mtodo readObject() del objeto ObjectInputStream creado: public final Object readObject() throws OptionalDataException, ClassNotFoundException, IOException;La Entrada/Salida en Java. Tambin pueden leerse, adems de objetos, valores de tipos de datos simples mediante cualquiera de los mtodos de la interface DataInput, que implementa la clase ObjectInputStream: Boolean readBoolean(); int readInt(); byte readByte(); String readLine(); char readChar(); long readLong(); double readDouble(); short readShort(); float readFloat(); int readUnsignedByte(); void readFully(byte b[]); int readUnsignedShort(); void readFully(byte b[], int desplaza, String readUTF();

int longitud); int skipBytes(int n) Todos estos mtodos generan excepciones de la clase IOException y EOFException. Para leer objetos y valores de tipos de datos simples, de un stream, evidentemente, deben ser recuperados en el mismo orden en que se introducen. Si se introducen objetos de las clases C1, C2, C3, C2 , deben ser recuperados en ese mismo orden C1, C2, C3, C2, El siguiente ejemplo lee y muestra los objetos y el entero guardado anteriormente en el fichero prueba.dat:

import java.io.*; import java.util.Date; class SerialLee { public static void main(String arg[]) { try { // Un InputStream subyacente del cul // leer los bytes FileInputStream f=new FileInputStream("prueba.dat"); // El objeto deserializador ObjectInputStream ost = new ObjectInputStream(f); Persona persona=(Persona)ost.readObject(); Date fecha=(Date)ost.readObject(); int entero=ost.readInt();

En realidad, la clase ObjectInputStream no implementa la interface DataInput, sino la interface ObjectInput, que es una subinterface de DataInput, por lo que hereda sus mtodos.La Entrada/Salida en Java.

System.out.println(persona); System.out.println(fecha); System.out.println(entero); ost.close(); } catch (IOException e) { System.err.println(e); { catch (ClassNotFoundException e) { System.err.println(e); { { { En los casos de lectura de objetos, es necesario realizar una conversin de tipo referencial, ya que el mtodo readObject() devuelve un objeto de la clase Object. Para ello hay que anteponer el nombre de la clase entre parntesis a la expresin a convertir. La salida del programa segn los datos almacenados en el ejemplo del punto anterior sera la siguiente: Victor:30 Tue Jul 15 18:10:00 GMT+01:00 1997

Personalizacin en la serializacin.

Una clase puede controlar por s misma cmo ser serializada, alterando qu datos sern almacenados o ledos, definiendo los mtodos writeObject() y readObject() con, exactamente, las siguientes signaturas: private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException; private void writeObject(java.io.ObjectOutputStream out) throws IOExceptionLa Entrada/Salida en Java.

Estos mtodos declaran los parmetros ObjectInputStream y ObjectOutputStream, por lo que puede accederse a sus mtodos. Entre ellos se encuentran: public final void defaultWriteObject() throws IOException; Este mtodo escribe la informacin del objeto por defecto: todos sus atributos que no sean static o transient o no sean serializables. Puede utilizarse para realizar la escritura por defecto y, despus, agregar al stream informacin adicional sobre el objeto. public final void defaultReadObject() throws IOException, ClassNotFoundException, NotActiveException; Este mtodo lee la informacin del objeto por defecto: todos sus atributos que no sean static o transient o no sean serializables. Puede utilizarse para realizar la lectura por defecto y, despus, leer del stream informacin adicional sobre el objeto. Vase el siguiente ejemplo que modifica la clase Persona de forma que serialice, adems de los atributos propios de Persona2 (nombre y edad), el

momento(Date) en que se escribe: import java.util.Date; import java.io.*; public class Persona2 implements java.io.Serializable{ private String nombre; private int edad; public Persona2(String s, int i) { nombre=s; edad=i; { public String toString() { return nombre+":"+edad; { private void writeObject(java.io.ObjectOutputStream out) throws IOException { // Escribir los atributos por defecto out.defaultWriteObject(); // Aadir la fecah de escritura out.writeObject(new Date()); { private void readObject(java.io.ObjectInputStream in)La Entrada/Salida en Java. throws IOException, ClassNotFoundException { // Leer los atributos por defecto in.defaultReadObject(); // Leer la fecha guardada Date fecha = (Date)in.readObject();

System.out.println("Objecto grabado en fecha: "+ fecha); { { Los programas para la escritura y para la lectura no necesitan de ninguna modificacin especial: ! import java.io.*; class SerialEscribe2 { public static void main(String arg[]) { try { FileOutputStream f=new FileOutputStream("prueba.dat"); ObjectOutputStream ost = new ObjectOutputStream(f); Persona2 persona=new Persona2("Victor",30); ost.writeObject(persona); ost.flush(); // vaciar el buffer ost.close(); } catch (IOException e) { System.err.println(e); { { { ! import java.io.*; class SerialLee2 {

public static void main(String arg[]) { try { FileInputStream f=new FileInputStream("prueba.dat"); ObjectInputStream ost = new ObjectInputStream(f); Persona2 persona=(Persona2)ost.readObject(); System.out.println(persona); ost.close(); } catch (IOException e) {La Entrada/Salida en Java. System.err.println(e); { catch (ClassNotFoundException e) { System.err.println(e); { { {

Archivos de Entrada/Salida.
El paquete java.io del API 1.2.x estndar de Java es uno de los ms extensos. Decidir cul es la clase ms adecuada para leer un fichero de texto lnea a lnea, o por ejemplo, para acceder a los bytes de una imagen, puede llegar a ser confuso para el programador nefito. Adems, las operaciones de entrada/salida suelen ser con frecuencia tareas costosas desde el punto de vista del rendimiento de la aplicacin. Java ofrece muchas maneras de llevar a cabo este tipo de operaciones y es muy importante saber cul es la clase que mejor se adapta a las necesidades de cada caso. La rapidez de una aplicacin Java depende en buena medida de la forma empleada para solucionar la entrada/salida. En sistemas como MS Windows o Unix (incluyend o Linux), en donde existe el concepto de terminal o consola de texto, el sistema operativo provee un mecanismo bsico de interaccin con el usuario conectando el flujo de datos proveniente del teclado a la llamada entrada estndar del

programa, mostrando la quot;salida estndarquot; del programa como texto desplegado en la pantalla. La entrada estndar y la salida estndar pueden redireccionarse, haciendo por ejemplo que se lea de un archivo y se escriba en otro. Un flujo de entrada / salida (I/O stream, Input / Output stream) representa una fuente desde la cual se reciben datos o un destino hacia el cual se envan datos. Un flujo de datos puede provenir o dirigirse hacia archivos en disco, dispositivos de comunicaciones, otros programas o arreglos en memoria. Los datos pueden ser bytes, tipos primitivos, caracteres propios de un idioma local, u objetos. Los flujos pueden simplemente transferir datos sin modificacin o manipular esos datos para transformarlos de diversas maneras como parte del proceso de transferencia. Sea cual sea el tipo de datos, un flujo se presenta como una secuencia de datos. Un flujo de entrada (in put stream) lee datos de una fuente, un item por vez. Un flujo de salida (output stream) escribe datos en un destino, un item por vez. Los programas necesitan comunicarse con su entorno, tanto para recoger datos e informacin que deben procesar, como para devolver los resultados obtenidos. En Java, la entrada desde teclado y la salida a pantalla estn reguladas a traves de la clase System. Esta clase pertenece al package java.lang System.in: Objeto de la clase InputStream preparado para recibir datos desde la entrada estndar del sistema (habitualmente el teclado). System.out: Objeto de la clase PrintStream que imprimir los datos en la salida estndar del sistema (normalmente asociado con la pantalla). System.out.println("Hola, Mundo!"); System.out.println(57); double numeroPI = 3.141592654; System.out.println(numeroPI); String hola = new String("Hola"); System.out.println(hola); System.out.println("Hola, Mundo! " + numeroPI); try { c=(char)System.in.read(); { catch(java.io.IOException ioex) { { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); String frase = br2.readLine(); La manera de representar estas entradas y salidas en Java es a base de streams (flujos de datos). Un stream es una conexin entre el programa y la fuente o destino de los datos. La informacin se trasladaen serie (un carcter a continuacin de otro) a travs de esta conexin. Esto da lugar a una forma general de representar muchos tipos de comunicaciones.

Por ejemplo, cuando se quiere imprimir algo en pantalla, se hace a travs de un stream que conecta el monitor al programa. Se da a ese stream la orden de escribir algo y ste lo traslada a la pantalla. Este concepto es suficientemente general para representar la lectura/escritura de archivos, la comunicacin a travs de Internet o la lectura de la informacin de un sensor a travs del puerto en serie. Existen dos reas que requieren atencin adicional cuando manejamos E/S con archivos: La inicializacin de los objetos de E/S con archivos, puede ser una tarea no tan exitosa. Puede ser que archivo que se desea abrir no encuentre, lo cual lanza la excepcin FileNotFoundException. Esto podrar ser porque la cadena entregada al constructor puede ser el nombre de un archivo inexistente o que no se encuentra en el directorio de trabajo del programa. Al momento de leer o escribir a un archivo se puede lanzar la excepcin IOException.

Leer un fichero de texto

El paquete java.io ofrece multitud de maneras de llevar a cabo de una de las operaciones de entrada/salida ms habituales: leer un fichero de texto. Lo primero que hay que tener en cuenta es que un fichero de texto es, como su proprio nombre indica, un fichero orientado a caracteres. Por lo tanto, es preciso utilizar una clase adecuada para este tipo de datos. En principio, la clase FileReader, que pertenece al paquete java.io.Reader, se ajusta perfectamente a nuestras necesidades. El siguiente fragmento de cdigo muestra cmo se puede leer un fichero de texto. FileReader fr = null; try { String sFilePath = "C:\\FICHEROS\\in.txt"; fr = new FileReader(sFilePath); char[] data = new char[1024]; int iCharsRead; StringBuffer sb = new StringBuffer(); while ((iCharsRead = fr.read(data, 0, 1024)) != -1) { sb.append(data, 0, iCharsRead); } System.out.println(sb.toString()); } catch (Exception e) { e.printStackTrace(); } finally { try { if (fr == null) fr.close(); } catch (Exception e) { e.printStackTrace(); } }

En primer lugar se define una variable perteneciente a la clase FileReader. Inicialmente toma el valor null. La parte principal del cdigo se encuentra dentro de un bloque try...catch...finally. Java garantiza que la clusula finally se ejecuta con independencia de lo que ocurra dentro del bloque try...catch. Por lo tanto la clasula finally es el lugar adecuado para cerrar el canal de lectura abierto. De este modo, se tiene la completa seguridad de que el recurso se libera al completo. La variable sFilePath almacena la ruta completa del fichero. Ntese que el smbolo \ debe escribirse dos veces porque es el carcter reservado para las secuencias de escape. Abrir el fichero es tan simple como crear una instancia de la clase FileReader, pasando como parmetro la ruta completa del fichero. A partir de este momento se pueden acceder al contenido del fichero de texto de muy diversas formas. Una de las ms eficientes consiste en leer bloques de caracteres y sta es la empleada en el ejemplo que se est mostrando. La variable data representa un array de elementos de tipo char, es decir, caracteres. Es capaz de almacenar hasta 1.024 caracteres. iCharsRead es una variable que se emplea para guardar el nmero de caracteres que de verdad se han ledo en cada llamada al mtodo read. Finalmente, un objeto de tipo StringBuffer es el que va a almacenar todos los caracteres ledos. El mtodo read recibe tres parmetros. El primero es el array de datos donde se van a depositar los caracteres ledos del fichero de texto. El segundo es la posicin del array a partir de la cual se van a despositar dichos caracteres. Finalmente, el ltimo de los parmetros representa el nmero mximo de caracteres que deben leerse, o lo que es lo mismo, el nmero mximo de caracteres que se pueden almacenar en el array a partir de la posicin indicada. Los valores 0 y 1.024 del ejemplo indican se van a leer hasta 1.024 caracteres en cada vuelta del bucle while. El mtodo read devuelve un valor de tipo int. ste contiene el nmero real de caracteres que finalmente se han ledo o 1 en el caso de que se haya llegado al final del fichero de texto. Este valor no tiene que coincidir con el nmero mximo de caracteres que se pueden almacenar en el array. Siguiendo con el ejemplo, lo ms normal es que se leean bloques completos de 1.024 caracteres hasta llegar al final del fichero, momento ste en el que se lee un bloque de un tamao probablemente menor a 1.024. La clase StringBuffer cuenta con varias versiones del mtodo append. Una de ellas se ajusta a la perfeccin al tipo de lectura que se est empleando. Recibe como parmetro un array de caracteres, la posicin dentro del array a partir de la cual se van a tomar los caracteres y por ltimo, el nmero de caracteres, a partir de la posicin inicial dada, que han de tomarse. El ltimo paso consiste en mostrar por la salida estndar de la consola el valor del StringBuffer, que no es ni ms ni menos que todo el contenido del fichero de texto. Para ejecutar este programa hay que escribir una clase de la siguiente manera: import java.io.*; public class IOExample1 { ... } y crear un mtodo esttico llamado main. Se debe incluir el cdigo a ejecutar: public static void main(String[] args) { ... }

Ejecutar es tan fcil como escribir en la lnea de comando:

Mejorar el rendimiento. El rendimiento del caso anterior puede mejorarse sensiblemente si se emplea la clase BufferedReader. sta utiliza un buffer intermedio de almacenamiento donde se guardan los caracteres del fichero de texto. Esto se produce de manera transparente al programador pero en realidad, cuando se llama al mtodo read, los caracteres se obtienen del buffer interno y no directamente del fichero. Leer caracteres de un fichero es una operacin costosa por lo que resulta muy beneficioso hacerlo en bloques. El buffer interno permite leer el fichero en bloques con independencia de lo que haga el programador, que puede obtener los datos carcter a carcter, lnea a lnea, o incluso tambin en bloques, como se ha visto en el ejemplo anterior. Para utilizar un canal del tipo BufferedReader no es necesario realizar muchos cambios sobre el ejemplo anterior. El esqueleto se mantiene casi inalterado, excepto por la declaracin del propio canal: BufferedReader br = null; try { ... } catch (Exception e) { e.printStackTrace(); } finally { try { if (br == null) br.close(); } catch (Exception e) { e.printStackTrace(); } } El objeto de tipo BufferedReader se crea a partir de una objeto FileReader: br = new BufferedReader(new FileReader(sFilePath)); y a partir de este momento el programa es idntico: char[] data = new char[1024]; int iCharsRead; StringBuffer sb = new StringBuffer(); while ((iCharsRead = br.read(data, 0, 1024)) != -1) { sb.append(data, 0, iCharsRead); } System.out.println(sb.toString());

Los ejemplos mostrados hasta el momento no suelen ser corrientes en aplicaciones reales. Obsrvese que la cantidad de memoria empleada sea considerable. En primer lugar, se ha utilizado un array de 1.024 caracteres. Pero lo ms importante es que cada bloque de caracteres procedente del fichero de texto se almacena en el objeto de tipo StringBuffer. sto implica un proceso interno de ampliacin de la cantidad de memoria asignanda a esa variable.

Si se lee un fichero de texto de 1 Mb, por ejemplo, el programa emplear 1 Mb de memoria solamente para mantener todo el fichero en memoria. Lo ms corriente, cuando se leen ficheros de texto, es buscar una determinada lnea, o una cadena de texto. La clase BufferedReader permite leer un fichero de texto lnea a lnea de una manera bastante eficiente. Lectura lnea a lnea. El mtodo readLine devuelve una cadena de texto con la lnea leda del fichero o null si ya se ha ledo todo el fichero. Los separadores vlidos de lneas son el carcter salto de lnea (\n) o el carcter retorno de carro (\r). String searchString = "..."; ... String sLine; while ((sLine = br.readLine()) != null) { if (sLine.indexOf(searchString) != -1) { ... break; } }

Archivos Aleatorios
Definicion: Los archivos de acceso aleatorio, al igual que lo que su cede usualmente con la memoria (RAM=Random Access Memory), permiten acceder a los datos en forma no secuencial, desordenada. Esto implica que el archivo debe estar disponible en su totalidad al momento de ser accedido, algo que no siempre es posible Acceso secuencial (flujos o quot;streamsquot;): En este caso los datos son ledos secuenci almente, desde el comienzo del archivo hasta el final (el cual muchas veces no se conoce a priori). Este es el caso de la lectura del teclado o la escritura en una consola de texto, no se sabe cundo el operador terminar de escribir. Concatenacin (tuberas o quot;pipesquot;): Muchas veces es til armar conexion es entre programas que corren simultneamente dentro de una misma mquina, de forma que lo que uno produce se enva por un tubo para ser recibido por el otro, que est esperando a la salida del tubo. Las tuberas o quot;pipesquot; cumplen esta funcin.

1. Formas de uso Los archivos de acceso secuencial son extremadamente tiles para la mayor a de las aplicaciones, pero a veces son necesarios archivos de acceso aleatorio que permiten acceder a sus contenido en forma no secuencial, o aleatoria. La clase RandomAccessFile del paquete java.io, implementa un archivo de acceso aleatorio. Puede ser usada tanto para lectura como para escritura de bytes. Todo objeto, instancia de RandomAccessFile soporta el concepto de puntero que indica la posici n actual dentro del archivo. Es un entero que empieza en 0 y se mide en bytes. RandomAccessFile provee comandos para operar sobre el puntero.

2. Constructores: public RandomAccessFile ( String name, String mode) throws FileNotFoundException public RandomAccessFile ( File file, String mode) throws FileNotFoundException i. Crea un archivo de acceso aleatorio. ii. El modo puede ser: 1. r : Se abre el archivo para solo lectura. 2. rw : Abre el archivo para lectura y escritura. a. Si el archivo an no existe, lo crea.

La clase RandomAccessFile implementa las interfaces DataInput y DataOutput, por lo que tiene acceso a todas las operaciones read() y write() de las clases DataInputStream y DataOutputStream que tambin implementan las interfaces DataInput y DataOutput respectivamente. Tambin se tienen mtodos para moverse dentro de un fichero: iii. long getFilePointer(): Devuelve la posicin actual del puntero del fichero. iv. void seek( long pos ): Coloca el puntero del fichero en una posicin determinada. La posicin se da como un desplazamiento en bytes desde el comienzo del fichero. La posicin 0 marca el comienzo de ese fichero. v. long length(): Devuelve la longitud del fichero. La posicin length() marca el final de ese fichero.

3. Ejemplo a. import java.io.*; b. public class Log { c. public static void main( String args[] ) throws IOException {

d. RandomAccessFile miRAFile; e. String s = &quot;Informacion a incorporar Tutorial de Java &quot;; f. miRAFile = new RandomAccessFile( &quot;java.txt&quot;,&quot;rw&quot; );

g. // Nos vamos al final del fichero h. miRAFile.seek( miRAFile.length() ); i. j. k. l. miRAFile.writeBytes( s ); miRAFile.close(); } }