Sei sulla pagina 1di 11

1.

El paquete java.IO La clase File. (Referencia: proyecto DLC01-File)

La entrada y/o salida de datos en un programa Java se puede hacer mediante clases del paquete java.io, las cuales conforman jerarquias muy amplias. Java soporta entrada y salida de datos hacia y desde archivos y otros dispositivos tales como conexiones de red, a travs de objetos genricamente llamados flujos [streams], que son estructuras de datos que permiten transferir bytes entre una fuente y un destino. Los streams se construyen en una forma muy particular y propia de Java, usando objetos de una clase para manejar entradas, en la construccin de objetos de otra clase para manejar entradas, o desde una clase para gestionar salidas, a otra. Estas conversiones se hacen mediante los contructores de las clases usadas. Cada conversion proporciona una mejora adicional al proceso de lectura y/o escritura de datos hacia y desde los programas. Cada stream agrega capacidades mejoradas, permitiendo al programador enviar datos con formato desde el programa y recibir datos formateados desde un archivo o hacia datos del buffer para mejorar la eficiencia de las actividades de I/O. Ampliaremos este tema en el apartado 2 de esta ficha de clase. Los conocidos objetos System.in (de la clase java.io.InputStream) y System.out (de la clase java.io.PrintStream) son un ejemplo de streams, pero el paquete java.io brinda una gran cantidad de otras clases para manejar IO. Algunos flujos almacenan datos en la memoria y envian datos hacia o desde el programa en bloques y no de a un byte a la vez. Esto se hace para optimizar los accesos a disco: slo cuando un bloque est completo y listo para ser transferido a disco, se efecta de una sla vez la operacin de grabacin. Cuando un stream almacena bloques de datos en la memoria buscando esa optimizacin, se dice que el mismo usa un buffer. Una clase especialmente util del paquete java.io, es la clase File. Un objeto de la clase File es una representacin abstracta de un archivo o de un directorio. Tcnicamente, un objeto de la clase File permite manejar el nombre de un archivo (o sea, su file descriptor) como un objeto dotado de propiedades y comportamiento especfico para el manejo del archivo asociado, y no como una simple cadena de caracteres. Entre las propiedades de un file descriptor, se encuentra el pathname del mismo. El pathname (o nombre de ruta) de un archivo es la secuencia de directorios que hay que seguir para llegar hasta el archivo. Como sabemos, el pathname puede ser absoluto o relativo. Si el pathname es absoluto, entonces no se requiere otra informacin para acceder al archivo. Pero si es relativo, entonces el pathname provisto debe entenderse en relacin a otro pathname que lo contiene. El hecho es que las reglas para formacin de pathnames son especficas de cada plataforma. En Unix, el carcter usado para separar dos nombres de directorios en un pathname es la barra normal ( /) pero en Windows es la doble barra invertida ( \\). Un pathname absoluto en Unix comienza con la barra normal (indicando el directorio raiz) y luego sigue el resto de los directorios por los que debe bajarse, separados con barra normal. Pero en Windows, un pathname absoluto comienza con una letra que especifica la unidad de disco usada, seguida de dos puntos ms doble barra invertida, y luego la secuencia de directorios a seguir: En Unix: En Windows: /archivos/dlc/notasdeclase C:\\archivos\\dlc\\notasdeclase

El ltimo nombre en secuencias de cualquiera de los dos tipos puede ser un directorio o un archivo comn, pero el resto de los nombres en el pathname deben ser directorios. Si el pathname es relativo en Unix no se coloca el prefijo del directorio raiz, en Windows no se escribe el disco. En Java, si aparece un pathname relativo se asume que debe entenderse con relacin al directorio actual del usuario y normalmente este directorio es aquel desde el cual se ejecut el proyecto. La clase File permite crear objetos que encapsulan estos nombres y abstraen estas molestas diferencias entre plataformas. Provee constantes tales como File.separator o File.separatorChar que indican cual es el caracter usado para separar nombres de directorios en la plataforma husped (la primera constante maneja el valor como un String por razones de simplicidad de uso, y la segunda lo hace como un valor char). Los valores sern: Constante File.separatorChar File.separator Valor en Unix / / Valor en Windows \\ \\

En la prctica, la clase File se usa para acceder a las propiedades de directorio de un archivo (o propiedades de file system del archivo). Un objeto de la clase File puede usarse para determinar si el archivo pedido existe, si se tiene permiso de lectura y/o grabacin sobre l, si es un directorio o un archivo comun, o para determinar su pathname entre otros servicios. En otras palabras, la clase File permite obtener las que podriamos llamar propiedades externas del archivo, pero no permite acceder al contenido del archivo para su consulta o modificacion. Adems de mtodos para consulta de propiedades externas, la clase File provee metodos para ajustar el valor de esas propiedades y tambin otros mtodos muy tiles: borrar un archivo ( delete() ), cambiar el nombre de un archivo ( renameTo() ), crear un directorio o carpeta ( mkdir() ) y metodos para obtener el listado de archivos de un directorio. Uno de esos metodos (el metodo list() ), retorna un arreglo de Strings con los nombres de todos los archivos contenidos en un directorio. En el proyecto DLC01-File mostramos la forma de usar ese metodo para desplegar (y eventualmente navegar) el contenido de un directorio. Mostramos ahora una tabla a modo de resumen de los principales mtodos de la clase File (tomada y resumida desde el javadoc de la clase provisto por Sun en su documentacin de las clases del lenguaje). Note que la tabla siguiente slo contiene una descripcin breve de cada uno de los mtodos: para mayor detalle, revisar la documentacin javadoc completa.

Resumen de Constructores
File(File parent, String child)

Crea una nueva instancia de la clase File, usando un pathname abstracto para el directorio padre (parent) y un pathname enn forma de cadena para el nombre del archivo hijo (child)
File(String pathname)

Crea una nueva instancia de la clase File, convirtiendo el pathname que entra como parmetro, en un pathname abstracto.
File(String parent, String child)

Crea una nueva instancia de la clase File tomando como parmetro dos cadenas para los pathnames padre (parent) e hijo (child).

File(URI uri)

Crea una nueva instancia de la clase File, convirtiendo el descriptor que viene en forma de URI hacia un pathname abstracto.

Resumen de Mtodos
boolean canRead()

Chequea si la aplicacin puede leer o no el archivo denotado por el objeto File.


boolean canWrite()

Chequea si la aplicacin puede modificar o no el archivo denotado por el objeto File.


int compareTo(File pathname)

Compara dos pathnames abstractos, lexicogrficamente.


boolean createNewFile()

Crea un archivo vaco, cuyo nombre coincidir con el representado por el objeto File. Slo se hace la creacin si no exista previamente un archivo con ese pathname.
static File createTempFile(String prefix, String suffix)

Crea un archivo vaco en el directorio por default de archivos temporales, usando como prefijo y sufijo las cadenas que entran como parmetro.
static File createTempFile(String prefix, String suffix, File directory)

Crea un archivo vaco en el directorio especificado por el parmetro directory por default de archivos temporales, usando como prefijo y sufijo las cadenas que entran como parmetro.
boolean delete()

Borra el archivo o directorio denotado por el objeto File.


void deleteOnExit()

Solicita que el archivo denotado por el objeto File sea borrado cuando la mquina virtual termine.
boolean equals(Object obj)

Verifica si este pathname abstracto es igual al que entra como parmetro.


boolean exists()

Verifica si el archivo o directorio denotado por el objeto File existe.


File getAbsoluteFile()

Retorna la forma absoluta del pathname abstracto denotado.


String getAbsolutePath()

Retorna el pathname absoluto de este pathname, en forma de cadena.


File getCanonicalFile()

Retorna la forma cannica de este pathname abstracto.


String getCanonicalPath()

Retorna la forma cannica de este pathname abstracto, en forma de cadena.


String getName()

Retorna el nombre del archivo o directorio denotado por el objeto.


String getParent()

Retorna una cadena con el pathname del directorio padre del archivo denotado por el objeto. Si no hay un pathname padre denotado, retorna null.
File getParentFile()

Retorna un objeto File con el pathname del directorio padre del archivo denotado por el objeto. Si no hay un pathname padre denotado, retorna null.
String getPath()

Convierte este pathname abstracto en un pathname en forma de String.


int hashCode()

Calcula un hash code para este pathname abstracto.


boolean isAbsolute()

Verifica si este pathname abstracto es absoluto.


boolean isDirectory()

Verifica si este pathname asbtracto es un directorio.


boolean isFile()

Verifica si el archivo denotado es un archivo normal.


boolean isHidden()

Verifica si el archivo denotado es un archivo oculto.


long lastModified()

Retorna el tiempo transcurrido desde la ltima modificacin del archivo denotado.


long length()

Retorna la longitud en bytes del archivo denotado.


String[] list()

Retorna un arrego de cadenas, con los nombres de los archivos contenidos, si el archivo denotado es un directorio. Si no es un directorio, retorna null.
String[] list(FilenameFilter filter)

Si el archivo denotado es un dircetorio, retorna un arreglo con los nombres de los archivos contenidos, que satisfagan el filtro que entra como parmetro en filter.
File[] listFiles()

Si el archivo denotado es un directorio, retorna un arreglo con objetos File representando a los pathnames abstractos de los archivos contenidos.
File[] listFiles(FileFilter filter)

Si el archivo denotado es un directorio, retorna un arreglo con objetos

File representando a los pathnames abstractos de los archivos contenidos, pero tales que satisfagan el filtro dado por filter.
File[] listFiles(FilenameFilter filter)

Si el archivo denotado es un directorio, retorna un arreglo con objetos File representando a los pathnames abstractos de los archivos contenidos, pero tales que satisfagan el filtro dado por filter.
static File[] listRoots()

Retorna un arreglo de objetos File denotando los direcctorios raiz disponibles.


boolean mkdir()

Crea un directorio, con el nombre denotado por el objeto File.


boolean mkdirs()

Crea un directorio con el nombre indicado por el objeto File, incluyendo cualquier directorio padre necesario (pero que no exista previamente)
boolean renameTo(File dest)

Renombra el archivo denotado por el objeto File. Retorna true en caso de xito, o false en caso contrario. Muchos aspectos del comportamiento de este mtodo son dependientes de la plataforma: la operacin de renombrado podra no ser capaz de mover un archivo desde un filesystem hacia otro (sabemos que en la plataforma Windows efectivamente as lo hace, pero no siempre se cumple en Linux), la operacin podra no ser "atmica" (en el sentido que podra requerir de varias suboperaciones a modo de macro) y adems podra no tener xito si ya existe un archivo con el mismo pathname. El valor de retorno del mtodo debera ser siempre chequeado para segurarse que la operacin de retorno tuvo xito.
boolean setLastModified(long time)

Cambia el tiempo de la ltima modificacin dle archivo o directorio.


boolean setReadOnly()

Marca el archivo o directorio denotado de forma que sea de slo lectura.


String toString()

Convierte a String el pathname abstracto denotado por el objeto.


URI toURI()

Construye un objeto URI que representa a este pahtname abstracto.


URL toURL()

Construye un objeto URL que representa a este pahtname abstracto.

En el mismo modelo DLC01-File, mostramos la forma usar la clase File para tomar archivos de disco y consultar sus propiedades. Para seleccionar un archivo desde el disco, la forma ms segura es recurrir a un cuadro de dilogo que incluya un explorador de directorios, y elegir el archivo con el mouse. De esta forma se evita tener que validar el nombre del archivo. Para ello usamos la clase javax.swing.JFileChooser la cual permite desplegar una ventana conteniendo a un navegador de directorios (browser) desde la cual se pueden seleccionar archivos para su uso posterior. Al usarla solo debe tenerse cuidado de algunos

detalles. El primero es que JFileChooser provee un metodo getSelectedFile() que retorna un objeto de la clase File que representa al archivo seleccionado. Y el segundo, es que si al desplegar un JFileChooser el usuario sale del mismo presionando el boton de cierre de la ventana o el boton Cancel, el mtodo getSelectedFile() retorna null, lo cual debe ser considerado en una aplicacion para evitar el error.

2.)

Gestin de Archivos de Texto. (Referencia: DLC02-Texto y DLC03-Editor )

Hemos visto que la clase File es usada para acceder a las propiedades de file system de un archivo dado (o sea, a sus propiedades externas) pero no al contenido del archivo. El contenido de un archivo se accede en general por medio del resto de las clases de java.io que como vimos, representan flujos o streams de datos. Para trabajar con streams de IO, Java maneja un esquema muy particular, basado en dos caractersticas:
i. En general, las clases que permiten abrir streams para usarlos como entrada de datos a una aplicacin, no son las mismas que se usan para abrir streams de salida. Las clases de control de flujo o streams estn claramente divididas entre clases de entrada y clases de salida. Las primeras se usan para leer datos desde un dispositivo (y no para enviar datos hacia ellos) y las segundas para enviar datos pero no para leerlos. Si se desea en una aplicacion tanto poder leer como poder enviar, deben usarse dos conjuntos de clases: uno para enviar, y el otro para leer. As (por ejemplo), la clase FileReader permite leer (pero slo leer) caracteres desde un stream de entrada, y la clase FileWriter permite grabar (y slo grabar) caracteres en un stream de salida. En general, tampoco es suficiente con usar objetos de una sla clase para completar una operacin de entrada o de salida, sino que deben usarse objetos de varias clases colaborando entre ellos para acceder al contenido de un archivo, de forma que cada una de las clases agrega capacidades y formato al trabajo de la otra. Normalmente, para acceder al contenido de un archivo, se precisa el uso de un par de clases: una de ellas se encarga del trabajo de acceso "a bajo nivel" (comunicacion con el dispositivo, lectura o grabacion de un byte o un caracter, etc.), y la otra del trabajo "de alto nivel" (comunicacion con la aplicacion, formateado de los bytes recibidos o a enviar, etc.) Se crea primero el objeto para la clase de bajo nivel usando su constructor, y luego se crea el objeto de la clase de alto nivel, pasndole a su constructor el objeto de "bajo nivel" antes creado. La clase de alto nivel provee mtodos para leer o grabar valores, y estos valores se van pasando entre las clases que comunican la aplicacion con el dispositivo.

ii.

En el caso de los archivos de texto, lo normal es usar las siguientes clases:


Para grabar: FileWriter: BufferedWriter: stream de bajo nivel que permite enviar caracteres directamente hacia un dispositivo. stream de alto nivel con buffer, que se puede conectar con un FileWriter y mejorar su eficiencia.

Para leer:

FileReader: BufferedReader:

stream de bajo nivel que permite leer caracteres directamente desde un dispositivo. stream de alto nivel con buffer, que se puede conectar con un FileReader y mejorar su eficiencia.

El siguiente esquema grfico ayuda a comprender la idea:

BufferedReader
+ readLine()

FileReader

Aplicacin
(en memoria) alto nivel bajo nivel

Archivo de texto
(disco)

BufferedWriter + newLine() + write()

FileWriter

La forma de crear objetos para lograr la comunicacin se muestra en el siguiente ejemplo. Notar que es prctica comn crear primero un objeto de la clase File a modo de file descriptor, y luego crear el resto de los objetos: Streams de salida (archivos de texto):
// creacin de objetos para gestin de streams de salida File f = new File(archivo.txt) ; FileWriter out = new FileWriter(f); BufferedWriter ofile = new BufferedWriter(out); // grabacin de cadenas en el archivo de texto ofile.write(Lnea de texto); ofile.newLine(); ofile.write(Otra lnea);

Streams de entrada (archivos de texto):


// creacin de objetos para gestin de streams de entrada File f = new File(archivo.txt); FileReader in = new FileReader(f); BufferedReader ifile = new BufferedReader (in); // lectura de una cadena String linea = ifile.readLine();

Las clases de bajo nivel FileReader y FileWriter permiten abrir un archivo (mediante sus constructores) y luego pueden tomar de (o enviar a) ese archivo caracteres con la codificacin adecuada. Los constructores usados en los dos ejemplos anteriores abren el archivo de forma que si ya exista elimina su contenido. No obstante, ambas clases proveen otros constructores, y algunos de ellos permiten abrir el archivo de forma de poder agregar caracteres sin perder el contenido anterior (o sea, abren el archivo en modo append):

FileReader: resumen de constructores


FileReader(File file)

Crea un FileReader que abre el archivo dado por el parmetro file.


FileReader(FileDescriptor fd)

Crea un FileReader que abre el archivo dado por el parmetro fd.


FileReader(String fileName)

Crea un FileReader que abre el archivo dado por el parmetro fileName.

FileWriter: resumen de constructores


FileWriter(File file)

Crea un FileWriter que abre el archivo dado por el parmetro file.


FileWriter(File file, boolean append)

Crea un FileWriter que abre el archivo dado por el parmetro file. El segundo parmetro (append) indica si los nuevos datos sern aadidos ( append=true) o si el contenido anterior ser borrado (append=false).
FileWriter(FileDescriptor fd)

Crea un FileWriter que abre el archivo dado por el parmetro fd.


FileWriter(String fileName)

Crea un FileWriter que abre el archivo dado por el parmetro fileName.


FileWriter(String fileName, boolean append)

Crea un FileWriter que abre el archivo dado por el parmetro fileName. El segundo parmetro (append) indica si los nuevos datos sern aadidos (append=true) o si el contenido anterior ser borrado (append=false).

Como se ve en los ejemplos, la clase BufferedReader provee el metodo readLine() que permite leer un string desde el dispositivo al cual accede el FileReader correspondiente. Del mismo modo, la clase BufferedWriter provee dos metodos utiles: write() y newLine(). El primero permite grabar una cadena en el dispositivo conectado al FileWriter correspondiente, y el segundo envia un caracter de salto de linea a ese dispositivo, compatible con la plataforma: notar que no todas las plataformas aceptan el caracter \n como indicador de salto de lnea, y la llamada al mtodo newLine() garantiza que se enve un caracter adecuado para la plataforma husped. Tanto BufferedReader como BufferedWriter son clases que trabajan con buffer: ambas utilizan un espacio de memoria intermedio, de cierto tamao, al cual envan los datos que se piden grabar o desde el cual toman los datos que se piden leer. Cuando ese espacio se

llena, recin entonces se enva el bloque completo al objeto de bajo nivel (un FileWriter en este caso) para ser grabado en disco. Algo similar ocurre en caso de hacer lecturas: el objeto de bajo nivel (un FileReader en este caso) va enviando al buffer los caracteres que lee, y desde ese buffer toma su entrada el objeto BufferedReader. El trabajo con buffer ayuda a optimizar los tiempos de IO al operar con dispositivos externos. Note que las clases BufferedReader y BufferedWriter proveen un par de constructores, y que en base al segundo constructor de cada clase se puede configurar el tamao del buffer a usar. Si se usa el primer constructor de cada clase, el tamao del buffer queda con tamao por default, el cual es lo suficientemente grande para la mayor parte de los usos esperados en archivos de texto:

BufferedReader: resumen de constructores


BufferedReader(Reader in)

Crea un stream de entrada con buffer, que usa un buffer con tamao por default.
BufferedReader(Reader in,int sz)

Crea un stream de entrada con buffer, que usa un buffer con tamao sz.

BufferedWriter: resumen de constructores


BufferedWriter(Writer out)

Crea un stream de salida con buffer, que usa un buffer con tamao por default.
BufferedWriter(Writer out,int sz)

Crea un stream de salida con buffer, que usa un buffer con tamao sz.

Finalmente, notar que salvo la mayora de los mtodos de la clase File, prcticamente todos los mtodos de las otras clases del paquete java.io pueden provocar alguna excepcin de la clase IOException (que es una excepcin de tipo chequeada) al usar sus metodos. Por lo tanto, la aplicacion debe declarar esa posibilidad, o capturar la excepcion con try - catch. El

proyecto DLC02-Texto muestra la forma bsica de operar (en consola estndar) con archivos de texto siguiendo este modelo. Y el proyecto DLC03-Editor muestra el desarrollo de un sencillo editor de textos planteado en base a las clases vistas aqu.

Bibliografa: Si bien los profesores de la ctedra preparan una serie de fichas de consulta y gua para los temas de la asignatura, debe entenderse que para un dominio completo de estos temas y para el desarrollo ptimo de las tareas y ejercicios que se piden es fuertemente recomendable que los alumnos estudien e investiguen a fondo en otras fuentes. Va para ello la siguiente bibliografa de consulta y ampliacin de temas:

Deitel, H., Deitel, P. (2005 o posterior). "Java Cmo Programar" . Mxico: Prentice Hall. ISBN: 970-26-0518-0 [disponible en biblioteca del Departamento de Sistemas] Eckel, B. (2002 aunque existe edicin posterior). "Piensa en Java". Madrid: Pearson Educacin. ISBN: 9788489660342. [disponible en biblioteca del Departamento de Sistemas] Horstmann, C., y Cornell G. (2000). Core Java 2 Volume I: Fundamentals. (Disponible en espaol) Upper Saddle River: Prentice Hall. ISBN: 84-205-4832-4 [disponible en biblioteca central] Horstmann, C., y Cornell G. (2001). Core Java 2 Volume II: Advanced Features. (Disponible en espaol) Palo Alto: Prentice Hall. ISBN: 84-8322-310-4 [disponible en biblioteca central]

Otras fuentes: Es obvio que si se trata de caractersticas del lenguaje y la plataforma Java, la fuente directa de consulta es la documentacin javadoc de Sun, de la cual se extrajeron las tablas de constructores y mtodos de las clases citadas en la ficha. Esas tablas (y toda la documentacin) estn originalmente disponibles en ingls, y aqu hemos provisto una traduccin, tan fiel como nos fue posible. Si trabaja on line, puede acceder a esa documentacin desde este enlace: http://java.sun.com/javase/6/docs/api/ (aunque obviamente, se espera que cada alumno ya haga bajado la documentacin desde el centro de descargas de Sun).

10

Ejercicios: Los siguientes ejercicios conforman la primera tarea para el tramo de estructuras de datos de disco, que deber ser desarrollada y subida al aula virtual por los alumnos:
a.) Desarrolle una aplicacin Java, que permita acceder desde un JFileChooser a un directorio elegido por el usuario. En ese directorio elimine todos los archivos cuya extensin sea .bak (asegrese de realizar pruebas sobre un directorio creado para esas pruebas...) Disee las clases que crea necesarias. Desarrolle una aplicacin Java que permita mover a un directorio temporal todos los archivos (que no sean directorios) de un directorio seleccionado desde un JFileChooser. Desarrolle una aplicacin que permita elegir un directorio desde un JFileChooser, y lo elimine del disco (deber aplicar recursin para hacer esto...) (y tener mucho cuidado... use slo directorios de prueba en unidades de disco extraibles... hasta que est seguro que hizo bien las cosas... )

b.)

c.)

11

Potrebbero piacerti anche