¿Por qué trabajar con archivos en Java no da miedo?
\n\nCada desarrollador, incluso si solo escribe backend en Java, tarde o temprano se enfrenta a la necesidad de guardar datos, leer una configuración o procesar un registro. Trabajar con archivos y el sistema de archivos en Java es una habilidad básica que transforma aplicaciones de consola "de juguete" en utilidades reales. Y sí, en 2024 no solo tenemos el viejo y querido File, sino también el potente java.nio.file.
En este artículo lo cubriremos todo: desde abrir un bloc de notas hasta manipular permisos de acceso. ¡Allá vamos!
\n\n1. El enfoque clásico: java.io.File
\n\nEmpecemos por el abuelo. La clase File apareció en Java 1.0 y todavía se usa. Pero seamos honestos: se trata más de metadatos que de contenido. Con ella puedes verificar si un archivo existe, crear una carpeta u obtener una lista de archivos.
import java.io.File;\n\npublic class FileExample {\n public static void main(String[] args) {\n File file = new File("/home/user/docs/notes.txt");\n \n System.out.println("El archivo existe: " + file.exists());\n System.out.println("Ruta absoluta: " + file.getAbsolutePath());\n System.out.println("Tamaño: " + file.length() + " bytes");\n \n // Creamos un directorio\n File dir = new File("/home/user/new_folder");\n if (dir.mkdir()) {\n System.out.println("Carpeta creada");\n }\n }\n}\n\nDesventaja: File no puede leer archivos grandes correctamente; para eso se necesitan flujos. Y no soporta enlaces simbólicos (soft links) de forma nativa. Por eso Sun (y luego Oracle) lanzaron NIO.
2. Lectura de archivos: de InputStream a BufferedReader
\n\nLeer es la operación más común. Si el archivo es de texto, usa BufferedReader — almacena datos en búfer y funciona rápido.
import java.io.BufferedReader;\nimport java.io.FileReader;\nimport java.io.IOException;\n\npublic class ReadFile {\n public static void main(String[] args) {\n try (BufferedReader br = new BufferedReader(new FileReader("data.txt"))) {\n String line;\n while ((line = br.readLine()) != null) {\n System.out.println(line);\n }\n } catch (IOException e) {\n System.err.println("Error de lectura: " + e.getMessage());\n }\n }\n}\n\nPara archivos binarios (imágenes, comprimidos) usa FileInputStream:
import java.io.FileInputStream;\nimport java.io.IOException;\n\npublic class ReadBinary {\n public static void main(String[] args) {\n try (FileInputStream fis = new FileInputStream("image.png")) {\n byte[] buffer = new byte[1024];\n int bytesRead;\n while ((bytesRead = fis.read(buffer)) != -1) {\n // procesamos el fragmento buffer[0..bytesRead]\n }\n } catch (IOException e) {\n e.printStackTrace();\n }\n }\n}\n\nImportante: usa siempre try-with-resources — esto garantiza el cierre del flujo, incluso si se lanza una excepción.
3. Escritura en archivos: BufferedWriter y FileOutputStream
\n\nEscribir es casi simétrico a leer. Para texto — BufferedWriter, para datos binarios — FileOutputStream.
import java.io.BufferedWriter;\nimport java.io.FileWriter;\nimport java.io.IOException;\n\npublic class WriteFile {\n public static void main(String[] args) {\n try (BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {\n bw.write("¡Hola, mundo!");\n bw.newLine();\n bw.write("Java es potente.");\n } catch (IOException e) {\n e.printStackTrace();\n }\n }\n}\n\nSi necesitas añadir al final del archivo en lugar de sobrescribirlo