Saltar al contenido principal

Ficheros

Hasta ahora hemos trabajado principalmente con datos que existen mientras nuestro programa está en ejecución.

Por ejemplo:

String nombre = "Mireia";

int edad = 20;

Estos datos se almacenan en memoria mientras el programa está funcionando. Pero cuando el programa termina, esos datos desaparecen.

Si queremos guardar información para poder utilizarla posteriormente, podemos almacenarla en un fichero.

Por ejemplo:

Programa



Guardar datos



usuarios.txt

Y cuando volvamos a ejecutar el programa:

usuarios.txt



Leer datos



Programa

Java proporciona diferentes clases para trabajar con ficheros.

En esta lección veremos:

File
FileReader
BufferedReader
FileWriter

Además, veremos cómo utilizar excepciones para controlar los posibles errores al trabajar con archivos.


File

La clase:

File

permite representar un fichero o una carpeta dentro de nuestro programa.

Para utilizarla debemos importar:

import java.io.File;

Y posteriormente crear una variable de tipo File:

File fichero = new File("datos.txt");

Aquí estamos creando un objeto File que representa:

datos.txt

Es importante entender que:

File fichero = new File("datos.txt");

no crea todavía el fichero.

Simplemente estamos creando un objeto fichero que representa la ruta del fichero `datos.txt.

Veremos como crear un fichero tanto para leer datos contenido en él como para guardar datos nuevos en él.

Crear un fichero

Si queremos crear físicamente el fichero en nuestro ordenador podemos utilizar:

createNewFile()

Por ejemplo:

import java.io.File;

public class Main {

public static void main(String[] args) {
// 1. Crear la variable que apuntará al fichero
File fichero = new File("datos.txt");

// 2. Crear el fichero en el ordenador
fichero.createNewFile();
}

}

Después de ejecutar el programa tendremos un fichero llamado datos.txt en la carpeta de nuestro proyecto:

Proyecto

├── Main.java

└── datos.txt

O en la ruta que especifiquemos:

import java.io.File;

public class Main {

public static void main(String[] args) {
// 1. Crear la variable que apuntará al fichero
File fichero = new File("/data/datos.txt");

// 2. Crear el fichero en el ordenador
fichero.createNewFile();
}

}
Proyecto

├── Main.java

└── data
|
└──datos.txt

Comprobar si un fichero existe

Antes de trabajar con un fichero podemos comprobar si existe utilizando:

exists()

Por ejemplo:

File fichero = new File("datos.txt");

if (fichero.exists()) {

System.out.println("El fichero existe");

} else {

System.out.println("El fichero no existe");

}

Esto puede ser útil antes de intentar leer un fichero.


Obtener información del fichero

La clase File también permite obtener información sobre el fichero.

Por ejemplo, podemos obtener su nombre:

File fichero = new File("datos.txt");

System.out.println(fichero.getName());

Resultado:

datos.txt

También podemos comprobar si es un fichero:

fichero.isFile()

Por ejemplo:

if (fichero.isFile()) {

System.out.println("Es un fichero");

}

También podemos comprobar si es una carpeta:

fichero.isDirectory()

Por ejemplo:

if (fichero.isDirectory()) {

System.out.println("Es una carpeta");

}

Eliminar un fichero

También podemos eliminar un fichero utilizando:

delete()

Por ejemplo:

File fichero = new File("datos.txt");

if (fichero.exists()) {

fichero.delete();

}

Esto eliminará el fichero.


File no sirve para leer el contenido

Es importante distinguir entre representar un fichero y leer su contenido.

Con:

File fichero = new File("datos.txt");

podemos trabajar con el fichero como elemento del sistema de archivos.

Podemos:

Comprobar si existe

Obtener su nombre

Comprobar si es un fichero

Comprobar si es una carpeta

Crear el fichero

Eliminarlo

Pero File no está pensado para leer directamente el texto que contiene.

Para leer el contenido utilizaremos:

FileReader

FileReader

La clase:

FileReader

permite leer el contenido de un fichero de texto.

Debemos importar:

import java.io.FileReader;

Y como antes, crear una variable de tipo FileReader:

FileReader lector = new FileReader("datos.txt");

Esto abre el fichero para poder leer su contenido.

Como abrir un fichero puede producir una excepción IOException, tendremos que controlarla.

Por ejemplo:

import java.io.FileReader;
import java.io.IOException;

public class Main {

public static void main(String[] args) {

try {

FileReader lector = new FileReader("datos.txt");

} catch (IOException e) {

System.out.println("No se ha podido abrir el fichero");

}

}

}

Leer caracteres con FileReader

FileReader permite leer caracteres del fichero.

Por ejemplo:

FileReader lector = new FileReader("datos.txt");

int caracter = lector.read();

El método:

read()

lee un carácter. Sin embargo, devuelve un int. Esto puede resultar extraño al principio.

Por ejemplo:

int caracter = lector.read();

Después podemos convertirlo a char:

char letra = (char) caracter;

Más adelante veremos como leer todos los caracteres de un fichero. De momento quédate con el concepto del read().

Cerrar un FileReader

Cuando terminamos de utilizar un lector debemos cerrarlo:

lector.close();

Por ejemplo:

try {

FileReader lector = new FileReader("datos.txt");

// Leer fichero

lector.close();

} catch (IOException e) {

System.out.println("Error al leer el fichero");

}

Esto es importante porque estamos trabajando con un recurso del sistema, de esta manera evitamos que el fichero quede "abierto" y haya confusión si luego volvemos a usarlo.


BufferedReader

Aunque FileReader permite leer un fichero, normalmente resulta más cómodo utilizar:

BufferedReader

BufferedReader permite leer texto de una forma más sencilla y eficiente.

Debemos importar:

import java.io.BufferedReader;

Normalmente utilizaremos BufferedReader junto con FileReader.

Por ejemplo:

FileReader lector = new FileReader("datos.txt");

BufferedReader buffer = new BufferedReader(lector);

Ahora es cuando nos será más fácil leer el contenido del fichero. De modo que puedes quedarte con la copla de que FileReader irá de la mano con BufferedReader.


Leer líneas con BufferedReader

La principal ventaja de BufferedReader es que podemos utilizar:

readLine()

para leer una línea completa.

Por ejemplo:

BufferedReader buffer =
new BufferedReader(
new FileReader("datos.txt")
);

String linea = buffer.readLine();

Si el fichero contiene:

Hola
Me llamo Joan
Tengo 20 años

la primera llamada a:

buffer.readLine()

devolverá:

Hola

La siguiente:

buffer.readLine()

devolverá:

Me llamo Joan

Y la siguiente:

buffer.readLine()

devolverá:

Tengo 20 años

Cuando llegamos al final del fichero:

buffer.readLine()

devuelve:

null

Así que para leer todas las líneas del fichero utilizaremos un bucle while, donde nos basemos en la idea de:

  • Mientras el contenido de la linea no sea null
    • lee la linea
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class Main {

public static void main(String[] args) {

try {

BufferedReader buffer =
new BufferedReader(
new FileReader("datos.txt")
);

String linea;

while ((linea = buffer.readLine()) != null) {

System.out.println(linea);

}

buffer.close();

} catch (IOException e) {

System.out.println("Error al leer el fichero");

}

}

}

El funcionamiento es:

readLine()



¿Devuelve null?

├── No
│ ↓
│ Mostrar línea
│ ↓
│ Volver a readLine()

└── Sí

Fin

Una vez ya tenemos el contenido de la líneas en la variable linea ya podremos hacer con el texto lo que queramos. Lo bueno es que el bucle while siempre será exactamente igual, solo cambiará qué harás con el contenido de la línea.

FileWriter

Hasta ahora hemos aprendido a leer ficheros. La otra operación más importante serña escribir en ellos, para ello utilizaremos:

FileWriter

Debemos importar:

import java.io.FileWriter;

Y crear el escritor o reader:

FileWriter escritor = new FileWriter("datos.txt");

Ahora podemos escribir contenido utilizando:

write()

Por ejemplo:

// 1. Crear el escritor
FileWriter escritor = new FileWriter("datos.txt");

// 2. Escribir en él
escritor.write("Hola");

// 3. Cerrar el escritor al acabar
escritor.close();

Después de ejecutar el programa, datos.txt contendrá:

Hola

Escribir varias líneas

Podemos utilizar write() varias veces:

FileWriter escritor = new FileWriter("datos.txt");

escritor.write("Hola\n");
escritor.write("Me llamo Adriana\n");
escritor.write("Estoy aprendiendo Java");

escritor.close();

El fichero contendrá:

Hola
Me llamo Adriana
Estoy aprendiendo Java

El carácter:

\n

representa un salto de línea.


Sobrescribir un fichero

Por defecto, cuando creamos un FileWriter de esta forma:

FileWriter escritor = new FileWriter("datos.txt");

el contenido anterior del fichero se reemplaza.

Por ejemplo, si tenemos:

datos.txt

Hola
Me llamo Adriana

y ejecutamos:

FileWriter escritor = new FileWriter("datos.txt");

escritor.write("Nuevo contenido");

escritor.close();

el fichero pasará a contener:

Nuevo contenido

y el contenido anterior se ha sobrescrito.


Añadir contenido al final

Si queremos añadir contenido sin borrar lo que ya existe, podemos utilizar otro constructor de FileWriter:

FileWriter escritor =
new FileWriter("datos.txt", true);

El segundo parámetro:

true

indica que queremos utilizar el modo append, es decir, añadir contenido al final.

Por ejemplo, si tenemos:

Hola
Me llamo Adriana

y hacemos:

FileWriter escritor =
new FileWriter("datos.txt", true);

escritor.write("\nEstoy aprendiendo Java");

escritor.close();

el fichero quedará:

Hola
Me llamo Adriana
Estoy aprendiendo Java

Escribir utilizando excepciones

Al igual que ocurre con FileReader, FileWriter puede producir una IOException.

Por ejemplo:

import java.io.FileWriter;
import java.io.IOException;

public class Main {

public static void main(String[] args) {

try {

FileWriter escritor =
new FileWriter("datos.txt");

escritor.write("Hola");

escritor.close();

} catch (IOException e) {

System.out.println(
"No se ha podido escribir el fichero"
);

}

}

}

Ejemplo completo

Vamos a crear un pequeño programa que guarde nombres en un fichero y después los lea.

Primero importamos las clases:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

Después podemos escribir los nombres:

FileWriter escritor =
new FileWriter("nombres.txt");

escritor.write("Jose\n");
escritor.write("Amanda\n");
escritor.write("Sofia\n");

escritor.close();

Después podemos leerlos:

BufferedReader lector =
new BufferedReader(
new FileReader("nombres.txt")
);

String nombre;

while ((nombre = lector.readLine()) != null) {

System.out.println(nombre);

}

lector.close();

La salida será:

Jose
Amanda
Sofia

Y tendremos un fichero:

nombres.txt

con el mismo contenido.


Errores frecuentes

Confundir File con el contenido del fichero

Esto:

File fichero = new File("datos.txt");

no lee el contenido.

Solamente representa el fichero.

Para leerlo podemos utilizar:

FileReader

y:

BufferedReader

Olvidar cerrar el fichero

Si utilizamos las clases tradicionales:

FileReader lector = new FileReader("datos.txt");

debemos cerrarlo cuando terminemos:

lector.close();

Lo mismo ocurre con FileWriter:

escritor.close();

Confundir read() con readLine()

FileReader utiliza:

read()

para leer caracteres.

Mientras que BufferedReader utiliza:

readLine()

para leer líneas completas.


Confundir sobrescribir con añadir

Esto:

new FileWriter("datos.txt")

sobrescribe el contenido anterior.

Mientras que:

new FileWriter("datos.txt", true)

añade contenido al final.


No controlar IOException

Operaciones como:

new FileReader("datos.txt")

o:

new FileWriter("datos.txt")

pueden producir:

IOException

Por eso debemos utilizar try-catch o throws.

Por ejemplo:

try {

FileReader lector =
new FileReader("datos.txt");

} catch (IOException e) {

System.out.println(
"No se ha podido abrir el fichero"
);

}