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"
);
}