Gestión de archivos en Java

09 de Octubre del 2016


Hola lectores, hoy hablaré sobre cómo podemos trabajar con archivos desde Java, nombrando las clases más utilizadas para ello y cómo usarlas a través de algún ejemplo.

txt

Archivos, ¿qué son?

Antes de hablar sobre cómo gestionamos los archivos debemos de conocer qué son, para ello tenemos esta sencilla explicación: un archivo es un conjunto de datos estructurados guardados en algún medio de almacenamiento que pueden ser utilizados por aplicaciones.

Está compuesto por:

  • Nombre: Identificación del archivo.
  • Extensión: Indica el tipo de archivo.

Tenemos también esta definición más técnica sacada directamente de la Wikipedia

Un archivo o fichero informático es un conjunto de bits que son almacenados en un dispositivo. Un archivo es identificado por un nombre y la descripción de la carpeta o directorio que lo contiene. A los archivos informáticos se les llama así porque son los equivalentes digitales de los archivos escritos en expedientes, tarjetas, libretas, papel o microfichas del entorno de oficina tradicional.

Clase File

La clase File además de proporcionarnos información sobre los archivos y directorios nos permite crearlos y eliminarlos.

Para ello esta clase nos permite crearlos utilizando:

File nombreFile = new File("/carpeta/archivo");

y borrarlos con:

nombreFile.delete();

Además de los anteriores disponemos de estos métodos para gestionarlos:

Método Descripción
createNewFile() Crea (si se puede) el fichero indicado
delete() Borra el fichero indicado
mkdirs() Crea el directorio indicado
getName() Devuelve un String con el nombre del fichero
getPath() Devuelve un String con la ruta relativa
getAbsolutePath() Devuelve un String con la ruta absoluta
getParent() Devuelve un String con el directorio que tiene por encima
renameTo() Renombra un fichero al nombre del fichero pasado como parámetro (se puede mover el fichero resultante a otra ruta, en caso de ser la misma se sobrescribirá)
exists() Boolean que nos indicará si el fichero existe
canWrite() Boolean que nos indicará si el fichero puede ser escrito
canRead() Boolean que nos indicará si el fichero puede ser leído
isFile() Boolean que indica si el fichero es un archivo
listFiles() Método que devuelve un array con los ficheros contenidos en el directorio indicado
isDirectory() Boolean que indica si el fichero es un directorio
lastModified() Devuelve la última hora de modificación del archivo
length() Devuelve la longitud del archivo

Ya que somos capaces de trabajar tanto archivos como directorios tenemos métodos que nos permiten diferenciarlos. Debajo de estas líneas tenemos un ejemplo para ello.

/* En este ejemplo asignamos la ruta del directorio utilizando
   la primera posición del array args[] del método main. En este segmento
   de código comprobamos si el array no está vacío para luego
   comprobar si el fichero es un directorio, en este caso
   guarda los nombres del contenido del directorio en un array
   para mostrarlos luego gracias al foreach */
if(args.length > 0) {
  File f = new File(args[0]);

    if(f.isDirectory()) {
      File[] ficheros = f.listFiles();

      System.out.println("Lista de los nombres de ficheros dentro del directorio");

      for(File file : ficheros)
        System.out.println("\t" + file.getName());
    }
}

A la hora de pasar el nombre de un archivo a través del array args[] podemos comprobar si éste existe o no, para que lo cree en caso contrario, y evitar posibles errores utilizando el código a continuación.

if(args.length > 0) {
  File fichero = new File(args[0]);

  if(!fichero.exists()) {
    try {
      fichero.createNewFile();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

Las demás clases de lectura y escritura de archivos que veremos a continuación son susceptibles de generar excepciones, por lo que debemos tratarlas siempre con try/catch y además tener la buena costumbre de utilizar el método close() para cerrarlos.

Un ejemplo por adelantado:

/* Este ejemplo de uso del try/catch escribe en un archivo txt,
   números aleatorios entre 1 y 10 */
try {
  FileWriter fl = new FileWriter("test.txt");
  PrintWriter pw = new PrintWriter(fl);

  for(int i = 0; i < 10; i++) {
    pw.println(i + 1);
    System.out.println(i + 1);
  }

  pw.close();
} catch(IOException e) {
  e.printStackTrace();
}

Clases FileWriter y PrintWriter

Ambas clases sirven para escribir caracteres en ficheros, simplemente PrintWriter es una mejora de la clase FileWriter (comparten el mismo padre java.io.Writer) que nos permite utilizar métodos adicionales.

/* Este ejemplo pregunta a un usuario unos datos para luego
   almacenarlos en el archivo ejercicio1.txt */
int numPersonas = 5;

int[] edad = new int[numPersonas];
String[] nombre = new String[numPersonas];
String[] apellido = new String[numPersonas];

try {
  /* Aunque no se utilice normalmente de esta forma aquí
     os pongo un ejemplo de uso para ambas clases */
  FileWriter fichero = new FileWriter("ejercicio1.txt");
  PrintWriter pw = new PrintWriter(fichero);

  for(int i = 0; i < numPersonas; i++) {
    System.out.print("\nDime el nombre del usuario " + (i + 1) + ": ");
    nombre[i] = Entrada.cadena();

    System.out.print("Dime el apellido del usuario " + (i + 1) + ": ");
    apellido[i] = Entrada.cadena();

    System.out.print("Dime la edad del usuario " + (i + 1) + ": ");
    edad[i] = Entrada.entero();

    pw.println("\nUsuario " + (i + 1) + "\tNombre: " + nombre[i] + "\tApellido: "
              + apellido[i] + "\tEdad: " + edad[i]);
  }

  pw.close();
} catch(IOException e) {
  e.printStackTrace();
}

De los métodos más útiles podemos destacar:

FileWritter  
write() Escribe uno o varios caracteres
flush() Limpia el flujo de datos
close() Cierra FileWriter para terminar la gestión con el archivo (internamente llama al método flush())
PrintWriter  
println() Escribe en el archivo el parámetro que le introduzcamos
append() Añade el carácter (char) o caracteres (CharSequence) específicos
checkError() Boolean que llama al método flush() y comprueba si hay algún error
close() Cierra PrintWriter para terminar la gestión con el archivo

Clases FileReader y BufferedReader

Es una buena práctica utilizar estas clases conjuntamente pues FileReader simplemente lee caracteres de un fichero y BufferedReader nos ayuda a guardarlos en un buffer para tratarlos de una forma más segura.

/* Este fragmento de código lee un archivo
   y lo muestra por la terminal */
File f = new File("ejercicio1.txt");

try {
  FileReader fr = new FileReader(f);
  BufferedReader br = new BufferedReader(fr);

  String linea = br.readLine();

  System.out.println();

  while(linea != null) {
    System.out.println(linea);
    linea = br.readLine();
  }

  br.close();
} catch(IOException e) {
  e.printStackTrace();
}

Los métodos con los que comúnmente trabajaremos son:

FileReader  
mark() Marca la posición actual
read() Lee uno o varios caracteres
reset() Reinicia la lectura
toString() Devuelve en forma de String el contenido del objeto
BufferedReader  
readLine() Lee una línea de texto
skip() Se salta “n” caracteres
close() Cierra la lectura del archivo

Comparar líneas

Si queremos comparar el texto que contiene un archivo con un texto que introduzcamos nosotros, a través de un String por ejemplo, hemos de ser conscientes que existe la posibilidad de que las mayúsculas no nos coincidan o incluso que se nos colara algún espacio al final o al principio del String, para ello podemos utilizar los métodos toLowerCase() para pasar todo el texto a minúscula o toUpperCase() para mayúscula y también utilizar el método trim() para quitar los espacios.

String lineaAComparar = "hola mundo";

if(lineaArchivo.toLowerCase().trim().equals(lineaAComparar.toLowerCase().trim()))
   // Las líneas son iguales

Como viene siendo habitual antes de despedirme recordaros que para cualquier duda con respecto a este post o el código tenéis mi correo electrónico iam@jmoral.es para que podáis escribirme o contactar a través de mi Twitter @owniz.

Un saludo. ツ

Comparte en →