Programación interactiva Oscar Bedoya oscarbed@eisc.univalle.edu.co Archivos Archivos Clase File • Resulta útil para recuperar información acerca de un archivo o directorio, entre la que se encuentra -Longitud del archivo en bytes -Fecha y hora de la última modificación -La ruta absoluta -En caso de ser un directorio, se puede conocer una lista con los nombres de archivos que contiene Además, cuando se tiene solo una referencia a un archivo o un directorio, se puede conocer cuál de los dos es. También se puede saber si realmente existe tal archivo o directorio Archivos Método Descripción boolean canRead() Devuelve true si se puede leer el archivo, en caso contrario devuelve false boolean canWrite() Devuelve true si se puede escribir el archivo, en caso contrario devuelve false boolean exists() Devuelve true si el nombre especificado como argumento en el constructor de File es un archivo o un directorio; en caso contrario devuelve false boolean isFile() Devuelve true si el nombre especificado como argumento en el constructor es un archivo boolean isDirectory() Devuelve true si el nombre especificado como argumento en el constructor es un directorio String getAbsolutePath() Devuelve un String con la ruta absoluta del archivo o directorio String getName() long length() long lastModified() String[] List() Devuelve un String con el nombre del archivo o directorio Devuelve la longitud de un archivo en bytes. Si el objeto File representa a un directorio, se devuelve 0 Devuelve una representación de la hora en la que se hizo la última modificación Devuelve un arreglo de cadenas que representan el contenido del directorio. Devuelve null si el objeto File no es un directorio Archivos Clase File • Los objetos File no abren archivos ni proporcionan herramientas para procesar archivos • Realmente, los objetos File se utilizan frecuentemente con objetos de otras clases de java.io para especificar los archivos o directorios que se van a manipular Archivos • Para crear un objeto de la clase File se especifica el nombre del archivo o directorio que se quiere asociar File objeto = new File(“datos.txt”); • En caso de que el archivo se encuentre dentro de un directorio, se utiliza un constructor que tiene dos parámetros, la ruta y el nombre del archivo File objeto = new File(“interativa/”, “ejemplo.dat”); Archivos • Para especificar un directorio se pasa su nombre al constructor File objeto = new File(“directorio”); Archivos Para leer el contenido de un archivo se debe tener en cuenta lo siguiente: • La clase FileReader se puede utilizar para abrir un archivo • Sin embargo, la clase FileReader no sabe cómo leer líneas de texto • La clase BufferedReader proporciona la funcionalidad de leer líneas de texto, pero no sabe cómo abrir un archivo • Se deben utilizar las clases FileReader y BufferedReader en conjunto para leer la información contenida en un archivo. Esto se conoce como envoltura de objetos de flujo Archivos Para envolver un objeto FileReader en un objeto BufferedReader se pasa el objeto FileReader al constructor de BufferedReader BufferedReader entrada=new BufferedReader(new FileReader(objeto)); Luego, se puede usar la referencia entrada para leer del archivo Archivos El archivo se lee por líneas. El método readLine devuelve en un String el contenido de la línea y avanza a la siguiente línea. En caso de que llegue al final del archivo, readLine devuelve null File objeto = new File(“datos.txt”); BufferedReader entrada=new BufferedReader(new while ((texto=entrada.readLine()) != null ) areatexto.append("\n" + texto ); FileReader(objeto)); Archivos PruebaFile Archivos Si es un archivo se muestra la ruta, la ruta absoluta y el contenido del archivo String nombreArchivo = campo.getText(); File objeto = new File(nombreArchivo); if ( objeto.exists() ) { areatexto.setText("\nRuta:” + objeto.getPath() + "\nRuta absoluta: " + objeto.getAbsolutePath() ); if ( objeto.isFile() ) { try { BufferedReader entrada = new BufferedReader(new FileReader( objeto ) ); String texto; areatexto.append( "\n\nCONTENIDO DEL ARCHIVO: \n" ); while ( ( texto = entrada.readLine() ) != null ) areatexto.append("\n" + texto ); } catch( IOException excepcion ) { JOptionPane.showMessageDialog( this, "ERROR EN ARCHIVO", "ERROR EN ARCHIVO", JOptionPane.ERROR_MESSAGE ); } } String nombreArchivo = campo.getText(); File objeto = new File(nombreArchivo); Se utilizan los métodos de la clase File if ( objeto.exists() ) { areatexto.setText("\nRuta:” + objeto.getPath() + "\nRuta absoluta: " + objeto.getAbsolutePath() ); if ( objeto.isFile() ) { try { BufferedReader entrada = new BufferedReader(new FileReader( objeto ) ); String texto; areatexto.append( "\n\nCONTENIDO DEL ARCHIVO: \n" ); while ( ( texto = entrada.readLine() ) != null ) areatexto.append("\n" + texto ); } catch( IOException excepcion ) { JOptionPane.showMessageDialog( this, "ERROR EN ARCHIVO", "ERROR EN ARCHIVO", JOptionPane.ERROR_MESSAGE ); } } Archivos Si es un directorio, se muestra su contenido if ( objeto.isDirectory() ) { String directorio[] = objeto.list(); areatexto.append( "\n\nContenido del directorio:\n"); } for ( int i = 0; i < directorio.length; i++ ) areatexto.append( directorio[ i ] + "\n" ); El método list devuelve un arreglo de Strings con los nombres de los subdirectorios y archivos. Se muestra cada elemento del arreglo Archivos Manejo de archivos con RandomAccessFile La clase RandomAccessFile proporciona todas las herramientas de las clases FileInputStream, FileOutputStream, DataInputStream y DataOutputStream que permiten escribir en un archivo Archivos • Para abrir un archivo por medio de la clase RandomAccessFile se pasa al constructor el nombre del archivo y el tipo de permiso RandomAccessFile archivo= new RandomAccessFile(nombre, permiso); donde permiso es un String que puede ser “r” para indicar que es de solo lectura, “w” para escritura y “rw” para lectura y escritura Archivos • Para leer de un archivo por medio de la clase RandomAccessFile se utiliza el método readLine() String linea; linea = archivo.readLine(); Archivos Problema: Desarrollar un traductor de tal forma que las palabras se almacenen en un archivo. El proceso de búsqueda de una palabra se realiza sobre el archivo TraductorX Archivos Problema: Desarrollar un traductor de tal forma que las palabras se almacenen en un archivo. El proceso de búsqueda de una palabra se realiza sobre el archivo El formato que se selecciona para almacenar los datos, consiste en colocar la palabra en español, seguido del carácter “#” y luego la palabra en inglés Archivos Problema: Desarrollar un traductor de tal forma que las palabras se almacenen en un archivo. El proceso de búsqueda de una palabra se realiza sobre el archivo TraductorX El formato que se selecciona para almacenar los datos, consiste en colocar la palabra en español, seguido del carácter “#” y luego la palabra en inglés Archivos • La clase StringTokenizer permite descomponer un String en tokens. Se pasa al constructor una cadena de caracteres y el símbolo que separa los tokens StringTokenizer tokens = new StringTokenizer(linea,simbolo); • Para conocer el siguiente token, se utiliza el método nextToken() actual = tokens.nextToken(); • Para saber si se tienen más tokens se hace; tokens.hasMoreTokens() Archivos Suponga que se tiene lo siguiente: String linea = “LIBRO#BOOK”; StringTokenizer tokens = new StringTokenizer(linea,”#”); System.out.println( tokens.nextToken() ); System.out.println( tokens.nextToken() ); Muestra los dos tokens LIBRO y BOOK Archivos Se toma la palabra del campo de texto TFPalabra y se compara con el primer token de la línea. Si coinciden se muestra el siguiente token, sino, se avanza a la siguiente línea String linea = new String(); String palabra = TFPalabra.getText(); try{ RandomAccessFile archivo = new RandomAccessFile("data.txt", "r"); linea = archivo.readLine(); int encontrado=0; while(linea!=null && encontrado==0){ StringTokenizer tokens = new StringTokenizer(linea, "#"); while (tokens.hasMoreTokens()){ String actual = tokens.nextToken(); } } if (actual.equals(palabra.toUpperCase()) ){ encontrado=1; TFTraduccion.setText(tokens.nextToken()); } else linea=archivo.readLine(); Se crea un objeto de RandomAccessFile para leer del archivo String linea = new String(); String palabra = TFPalabra.getText(); try{ RandomAccessFile archivo = new RandomAccessFile("data.txt", "r"); linea = archivo.readLine(); int encontrado=0; while(linea!=null && encontrado==0){ StringTokenizer tokens = new StringTokenizer(linea, "#"); while (tokens.hasMoreTokens()){ String actual = tokens.nextToken(); } } if (actual.equals(palabra.toUpperCase()) ){ encontrado=1; TFTraduccion.setText(tokens.nextToken()); } else linea=archivo.readLine(); • Si el token coincide con la palabra a traducir se muestra en el campo de texto. • Sino, se avanza a la siguiente línea Archivos Incorporando JFileChooser para el manejo de archivos Archivos + data.txt Archivos Para mostrar el cuadro de dialogo se utiliza el método showOpenDialog JFileChooser selectorArchivo = new JFileChooser(); int resultado = selectorArchivo.showOpenDialog(this); if (resultado == JFileChooser.CANCEL_OPTION) System.out.println("No seleccionó ningun archivo"); if (resultado == JFileChooser.APPROVE_OPTION) File nombreArchivo=selectorArchivo.getSelectedFile(); Archivos Para mostrar el cuadro de dialogo se utiliza el método showOpenDialog JFileChooser selectorArchivo = new JFileChooser(); int resultado = selectorArchivo.showOpenDialog(this); if (resultado == JFileChooser.CANCEL_OPTION) System.out.println("No seleccionó ningun archivo"); if (resultado == JFileChooser.APPROVE_OPTION) //procesar informacion El método showOpenDialog devuelve un número entero. Para saber si se hizo clic en Cancelar se utiliza la constante JFileChooser.CANCEL_OPTION y cuando se selecciona un archivo se tiene la constante JFileChooser.APPROVE_OPTION JFileChooser selectorArchivo= new JFileChooser(); int resultado = selectorArchivo.showOpenDialog(this); if (resultado == JFileChooser.CANCEL_OPTION) System.out.println("No seleccionó ningún archivo"); if (resultado == JFileChooser.APPROVE_OPTION) { File nombreArchivo = selectorArchivo.getSelectedFile() ; Se muestra el FileChooser. Se considera el caso en que no seleccione ningún archivo if (nombreArchivo==null || nombreArchivo.getName().equals("")) JOptionPane.showMessageDialog(null, "Nombre de archivo incorrecto”); else { try { RandomAccessFile r = new RandomAccessFile( nombreArchivo , "r"); String linea=r.readLine(); while (linea!=null){ areatexto.append("\n" + linea); datos.addElement(linea); linea = r.readLine(); } r.close(); } } } catch(IOException e){ System.out.println("Error al abrir el archivo"); } JFileChooser selectorArchivo= new JFileChooser(); int resultado = selectorArchivo.showOpenDialog(this); if (resultado == JFileChooser.CANCEL_OPTION) System.out.println("No seleccionó ningún archivo"); if (resultado == JFileChooser.APPROVE_OPTION) { File nombreArchivo = selectorArchivo.getSelectedFile() ; Se maneja el caso en que no escriba un nombre de archivo válido if (nombreArchivo==null || nombreArchivo.getName().equals("")) JOptionPane.showMessageDialog(null, "Nombre de archivo incorrecto”); else { try { RandomAccessFile r = new RandomAccessFile( nombreArchivo , "r"); String linea=r.readLine(); while (linea!=null){ areatexto.append("\n" + linea); datos.addElement(linea); linea = r.readLine(); } r.close(); } } } catch(IOException e){ System.out.println("Error al abrir el archivo"); } JFileChooser selectorArchivo= new JFileChooser(); int resultado = selectorArchivo.showOpenDialog(this); if (resultado == JFileChooser.CANCEL_OPTION) System.out.println("No seleccionó ningún archivo"); if (resultado == JFileChooser.APPROVE_OPTION) { File nombreArchivo = selectorArchivo.getSelectedFile() ; if (nombreArchivo==null || nombreArchivo.getName().equals("")) JOptionPane.showMessageDialog(null, "Nombre de archivo incorrecto”); else { try { RandomAccessFile r = new RandomAccessFile( nombreArchivo , "r"); String linea=r.readLine(); while (linea!=null){ areatexto.append("\n" + linea); datos.addElement(linea); linea = r.readLine(); } r.close(); } } Cada línea del archivo se guarda temporalmente en un vector } catch(IOException e){ System.out.println("Error al abrir el archivo"); } Archivos Procesar muestra la información del archivo separando cada línea que lo compone por el carácter “-” if (evento.getSource()==procesar) { areatexto.append("\n\n * Análisis *\n"); } for (int i=0 ; i<datos.size() ; i++) { String linea = (String.valueOf(datos.elementAt(i))); areatexto.append(" - " + linea); } Archivos Guardar los cambios efectuados en el área de texto. Se pueden adicionar más palabras para completar el traductor Archivos Una forma de almacenar datos en un archivo es por medio de un flujo (PrintStream) • Se declara el flujo PrintStream flujoSalida = null; • Se muestra el dialogo para guardr el archivo int resultado = selectorArchivo.showSaveDialog(this); • Se guardar en un objeto File el nombre del archivo File nombreArchivo = selectorArchivo.getSelectedFile(); • Se crea el flujo de salida flujoSalida = new PrintStream(new FileOutputStream(nombreArchivo) ); Archivos Una forma de almacenar datos en un archivo es por medio de un flujo (PrintStream) • Se declara el flujo PrintStream flujoSalida = null; • Se muestra el dialogo para guardr el archivo int resultado = selectorArchivo.showSaveDialog(this); • Se guarda en un objeto File el nombre del archivo File nombreArchivo = selectorArchivo.getSelectedFile(); • Se crea el flujo de salida flujoSalida = new PrintStream(new FileOutputStream(nombreArchivo) ); Archivos Una forma de almacenar datos en un archivo es por medio de un flujo (PrintStream) • Para escribir en el flujo se utiliza el método println flujoSalida.println( areatexto.getText() ); • Cuando se termine de escribir, se debe cerrar el archivo flujoSalida.close(); Archivos ver parte del oyente para guardar Archivos Problema: Desarrollar una aplicación Java que permita manejar los datos de los estudiantes. La aplicación debe permitir la búsqueda, adición y consulta de los estudiantes. La información se debe almacenar en un archivo Archivos1 + estudiantes.txt Archivos Considere el siguiente formato para almacenar la información de los estudiantes. Se separa por TAB (tabulación) los datos de cada estudiante Archivos Para la búsqueda, se digita el código y se oprime Buscar. Se busca en el archivo llamado estudiantes.txt -En caso de que se encuentre, se completan los campos de textos con la información respectiva -Si no se encuentra se muestra un mensaje Archivos1 ver método buscarEstudiante Archivos Para adicionar los datos de un nuevo estudiante, se utilizará ahora una forma alternativa de escribir en un archivo Se hará completamente utilizando la clase RandomAccesseFile. Específicamente, utilizando un método que permite ubicarse en la última línea del mismo para escribir allí Archivos • Crear la referencia al archivo RandomAccessFile file = new RandomAccessFile("estudiantes.txt", "rw"); • Ubicarse en el ultimo registro del archivo file.seek(file.length()); • Escribir en el archivo file.writeBytes(datosEstudiante); • Cerrar el archivo file.close(); Archivos • Crear la referencia al archivo RandomAccessFile file = new RandomAccessFile("estudiantes.txt", "rw"); • Ubicarse en el ultimo registro del archivo file.seek(file.length()); • Escribir en el archivo file.writeBytes(datosEstudiante); • Cerrar el archivo file.close(); •seek permite ubicarse en la posición indicada •writeBytes permite escribir en un archivo RandomAccessFile Archivos Cuando un programa necesita manipular el conjunto de datos almacenado previamente en un archivo, resulta más eficiente hacer una copia del archivo en un Vector Cuando inicia la aplicación se copia la información a un vector, se realizan las modificaciones sobre el vector y cuando el usuario vaya a cerrar la aplicación, se pasa el contenido del vector al archivo Actualizar y Eliminar son operaciones que requieren mayor control sobre el conjunto de datos Archivos2 public class Estudiante { private String codigo, nombre; private int edad; private double promedio; } public Estudiante(String c, String n, int e, double p){ codigo = c; nombre = n; edad = e; promedio = p; Estudiante } String codigo, nombre; public String obtenerCodigo(){ int edad; return codigo; double promedio; } public String obtenerNombre(){ Estudiante() return nombre; public String obtenerCodigo() } public String obtenerNombre() public int obtenerEdad(){ public int obtenerEdad() return edad; public double obtenerPromedio() } public double obtenerPromedio(){ return promedio; } datos unEstudiante 10066043 Sarah Meyer 25 4.5 unEstudiante 6106787 OsCaR 27 4.6 unEstudiante 9709555 Sophie 18 4.0 public void cargarDatos() { try{ RandomAccessFile file = new RandomAccessFile("estudiantes.txt", "r"); String linea = file.readLine(); while(linea!=null){ StringTokenizer tokens = new StringTokenizer(linea, "\t"); Se llama a este método en el constructor while (tokens.hasMoreTokens()){ } String codigo = String.valueOf(tokens.nextToken()); String nombre = String.valueOf(tokens.nextToken()); int edad = Integer.parseInt(tokens.nextToken()); double promedio = Double.parseDouble(tokens.nextToken()); Estudiante objeto = new Estudiante(codigo, nombre, edad, promedio); datos.addElement(objeto); linea=file.readLine(); } } } catch(IOException e){ System.out.println("Error al abrir el archivo"); } Archivos Adicionar un estudiante consiste en agregarlo al vector Archivos2 ver oyente adicionar, buscar y eliminar public static void guardarDatos() { try{ flujo= new PrintStream(new FileOutputStream("estudiantes.txt") ); } catch (IOException e) { System.out.println("Error al abrir el archivo"); } try{ for (int i=0 ; i<datos.size() ; i++) { String linea; linea = ((Estudiante)datos.elementAt(i)).obtenerCodigo() + "\t" + ((Estudiante)datos.elementAt(i)).obtenerNombre() + "\t" + ((Estudiante)datos.elementAt(i)).obtenerEdad() + "\t" + ((Estudiante)datos.elementAt(i)).obtenerPromedio() ; flujo.println(linea); } } catch(Exception e) {System.out.println("Error al abrir el archivo");} flujo.flush(); flujo.close(); } Para guardar los datos, se escribe, línea por línea, el contenido del vector public static void main(String[] args) { Archivos2 aplicacion = new Archivos2(); WindowListener l = new WindowAdapter() { public void windowClosing(WindowEvent e) { guardarDatos(); System.exit(0); } }; aplicacion.addWindowListener(l); aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); } Se modifica el método windowClosing para que haga el llamado al método guardarDatos()