1. Navegación de Archivos e I/O Expositor: Alex http://javatutoriales.blogspot.com/ Se permite hacer preguntas en cualquier momento.
2. I/O I/O es un gran tópico en general, y las APIs de Java para uso, tanto de entrada como de salida, son también bastante aplia. Una discusión general de I/O puede incluir tópicos como I/O de archivos, I/O de consola, I/O de threads, I/O de alto rendimiento, I/O orientado a bytes, I/O orientado a caracteres, filtros y wrapping de I/O, serialización, etc. Afortunadamente en el examen I/O esta restringido a archivos de caracteres y Serialización. 21/04/2011 Alex Montoya - SCJP 5 2
3. Clases de I/O para el Examen File: Es una representación abstracta de un archivo o directorio. Se usa para leer o escribir datos a un alto nivel FileReader: Es usada para leer archivos de caracteres a través de múltiples métodos read() BufferedReader: Es usada para hacer a las clases Reader de bajo nivel más eficientes y fáciles de usar. FileWriter: Es usada para escribir archivos de caracteres a través de múltiples métodos write() BufferedWriter: Es usada para hacer a las clases Writer de bajo nivel más eficientes y fáciles de usar PrintWriter: A partir de la versión 5 es posible usarla como wrapper de diversas clases de escritura de archivos 21/04/2011 Alex Montoya - SCJP 5 3
4. Creando Archivos Usando la Clase File Los objetos de tipo File son usados representar archivos (pero no los datos en ellos) o directorios que existen en el disco físico de la computadora: import java.io.*; class Escritor { public static void main(String [] args) { File file = new File(“archivo1.txt"); } } 21/04/2011 Alex Montoya - SCJP 5 4
5. Creando Archivos Usando la Clase File (2) Cuando creamos una nueva instancia de la clase File no estamos creado el archivo, solo el nombre. Cuando ya tenemos este objeto, hay muchas formas de crear el archivo: import java.io.*; class Escritor { public static void main(String [] args) { try { boolean nuevo = false; File file = new File (“archivo1.txt"); System.out.println(file.exists()); nuevo = file.createNewFile(); System.out.println(nuevo); System.out.println(file.exists()); } catch(IOException e) { } } } 21/04/2011 Alex Montoya - SCJP 5 5
6. Usando FileWriter y FileReader En la práctica no se usan FileReader y FileWriter si ser envueltas, sin embargo en el examen se espera que sepan cómo funcionan: class Escritor2 { public static void main(String [] args) { char[] entrada = new char[50]; int tamaño = 0; try { File file = new File(“archivo2.txt"); FileWriter fw = new FileWriter(file); fw.write(“saludosamigos"); fw.flush(); fw.close(); FileReader fr = new FileReader(file); tamaño = fr.read(entrada); System.out.print(tamaño + " "); for(char c : entrada) System.out.print(c); fr.close(); }catch(IOException e) { } } } 21/04/2011 Alex Montoya - SCJP 5 6
7. Usando FileWriter y FileReader (2) Esto es lo que ocurre en el código anterior: FileWriter fw = new FileWriter(file) hace tres cosas: Crea una nueva referencia a un FileWriter llamada fw Crea un nuevo objeto FileWriter y lo asigna a la referencia fw Crea el archivo nuevo vacío en disco duro Escribimos 15 caracteres en el archivo con el método write(), hacemos un flush() y un close() Creamos un nuevo FileReader, que abre un archivo para lectura El método read() lee el archivo completo, un carácter a la vez, y lo ponen en el char[] entrada Imprimimos el número de caracteres que se leyeron, e imprimimos después cada uno de los caracteres colocados en el char[] entrada, y cerramos el archivo 21/04/2011 Alex Montoya - SCJP 5 7
8. flush() y close() Cuando escribimos datos en un stream, ocurre un proceso de buffering, y no podemos estar seguros cuándo se enviará el último trozo de datos. Podemos realizar muchas operaciones de escritura en un stream antes de cerrarlo, e invocar el método flush() que los últimos datos que enviamos han sido escritos en el archivo. Cada vez que terminamos de escribir un archivo, ya sea para leer o para escribir, debemos llamar a close(). Cuando hacemos I/O de archivos estamos usando recursos caros y limitados del sistema operativo, y cuando invocamos a close()liberamos estos recursos. 21/04/2011 Alex Montoya - SCJP 5 8
9. Usando FileWriter y FileReader (3) El programa anterior funciona, sin embargo presenta algunas limitaciones: Cuando escribimos los datos en el archivo, insertamos de forma manual los separadores de línea. Cuando leemos los datos los ponemos en un arreglo. Al tratarse de un arreglo es necesario declarar su tamaño, por lo que si no lo hacemos del tamaño adecuado tendremos problemas al leer estos datos. Es por estas limitaciones que tipicamente usamos clases de más alto nivel como BufferedReader o BufferedWriter en combinación con FileReader o FileWritter. 21/04/2011 Alex Montoya - SCJP 5 9
10. Combinando Clases de I/O Todo el sistema de I/O de Java está diseñado para usar muchas clases en combinadas. Combinar estás clases es llamado envolver (wrapping) y algunas veces es llamado encadenar (chaining). El paquete java.io contiene alrededor de 50 clases, 10 interfaces, y 15 excepciones. Cada clase en el paquete tiene un propósito muy específico, y las clases están diseñadas para ser combinadas con otras para manejar una variedad de situaciones. 21/04/2011 Alex Montoya - SCJP 5 10
11. Mini API de java.io Clase Clase Base Argumentos de los constructores principales Métodos Importantes File Object File, String createNewFile() String delete() String, String exists() isDirectory() isFile() list() mkdir() renameTo() FileWriter Writer File close() String flush() write() BufferedWriter Writer Writer close() flush() newLine() write() PrintWriter Writer File close() String flush() OutputStream printf() Writer println() write() FileReader Reader File read() String read() BufferedReader Reader Reader readLine() 21/04/2011 Alex Montoya - SCJP 5 11
12. Decidiendo qué Clases Usar Ahora busquemos una mejor forma de escribir datos en un archivo y leer los datos nuevamente a memoria. Este es el proceso que clases necesitamos para escribir los datos: 21/04/2011 Alex Montoya - SCJP 5 12 Sabemos que queremos usar un objeto File. Así que cualquier otra clase debe tener un constructor que reciba un File. Buscamos un método que nos permita hacer esta tarea de forma más sencilla. Construimos el objeto de la clase necesaria y lo utilizamos
13. Decidiendo qué Clases Usar (2) Por lo que el nuevo código puede quedar de la siguiente forma: File file = new File(“archivo.txt”); PrintWriter pw = new PrintWriter(file); fw.println(“saludos”); fw.println(“amigos”); 21/04/2011 Alex Montoya - SCJP 5 13
14. Decidiendo qué Clases Usar (3) Para leer los datos hacemos lo mismo: File file = new File(“archivo.txt”); FileReader fr = new FileReader(file); BufferedReader br = new BufferedReader(fr); String datos = br.readLine(); 21/04/2011 Alex Montoya - SCJP 5 14
15. Trabajando con Archivos y Directorios Ya habíamos dicho que la clase File es usada para crear archivos y directorios. Además los métodos de File pueden ser usados para borrar directorios, renombrar archivos, saber si un archivo existe, crear archivos temporales, cambiar los atributos de un archivo, y diferenciar entre archivos y directorios. 21/04/2011 Alex Montoya - SCJP 5 15
16. Trabajando con Archivos y Directorios (2) Además vimos que: File file = new File("foo"); Crea un nuevo objeto File, y puede hacer una de dos cosas: Si “foo” no existe, crea el archivo Si “foo” existe, el nuevo File refiere al archivo 21/04/2011 Alex Montoya - SCJP 5 16
17. Trabajando con Archivos y Directorios (3) File file = new File(“foo”); NUNCA crea el arcivo. Hay dos formas de crearlo: Invocar el método createNewFile del objeto File 2. Crear un Reader o un Writer o un Stream. Específicamente, FileReader, FileWriter, PrintWriter, FileInputStream, o FileOutputStream. Cada vez que creamos una instancia de una de estas clases, creamos automáticamente un archivo, a menos que ya exista. 21/04/2011 Alex Montoya - SCJP 5 17
18. Trabajando con Archivos y Directorios (4) Crear un directorio es similar a crear un archivo. Es un proceso de dos fases; primero creamos un objeto directorio (File); después creamos el directorio usando el método mkdir(). File directorio = new File(“dir”); directorio.mkdir(); Una vez que tenemos el directorio, ponemos archivos en el: File archivo = new File(directorio, “archivo.txt”); archivo.createNewFile(); 21/04/2011 Alex Montoya - SCJP 5 18
19. Trabajando con Directorios Hay que tener cuidado cuando trabajamos con directorios. Como hemos visto, construir un Reader o un Writer crea de forma automática un archivo si no existe, pero esto no funciona con directorios: File directorio = new File(“dir”); File archivo = new File(directorio, “archivo.txt”); archivo.createNewFile(); 21/04/2011 Alex Montoya - SCJP 5 19
20. Trabajando con Directorios (2) Un objeto File puede referir a un archivo o un directorio. Para verificar a qué refiere podemos usar los métodos isFile() isDirectory() 21/04/2011 Alex Montoya - SCJP 5 20
21. Trabajando con Directorios (3) File dir = new File(“dir"); System.out.println(dir.isDirectory()); File archivo = new File(dir, “archivo.txt"); System.out.println (archivo.isFile()); FileReader fr = new FileReader(archivo); BufferedReader br = new BufferedReader(fr); String s; while( (s = br.readLine()) != null) System.out.printIn(s); 21/04/2011 Alex Montoya - SCJP 5 21
22. Otros Métodos Útiles Además de crear archivos los métodos de la clase File nos permiten hacer cosas como renombrar archivos y derectorios, y borrar archivos y directorios con los métodos renameTo y delete respectivamente: File dir = new File(“dir”); File nuevo = new File(“otro”); dir.renameTo(nuevo); dir.delete(); 21/04/2011 Alex Montoya - SCJP 5 22
23. Otros Métodos Útiles (2) Hay algunas cosas importantes que hay que saber sobre delete y renameTo: delete: No podemos borrar directorios que no estén vacíos renameTo: Debemos dar al objeto File existente un objeto nuevo File válido con el nombre que queramos. renameTo: Podemos renombrar un directorio aún si este no está vacio. 21/04/2011 Alex Montoya - SCJP 5 23