CodeGym /Cursos /JAVA 25 SELF /Especificar la codificación al leer/escribir archivos

Especificar la codificación al leer/escribir archivos

JAVA 25 SELF
Nivel 37 , Lección 2
Disponible

1. Introducción

Seamos sinceros desde el principio: si alguna vez has visto en lugar de texto en ruso algo como Привет, ya eres víctima de una codificación incorrecta. Esto sucede cuando el archivo se guardó con una codificación y se lee con otra. Por ejemplo, el archivo se guardó como UTF-8 y se lee como Windows-1251, o al revés.

Java, por defecto, utiliza la codificación del sistema, que puedes averiguar así:

System.out.println(System.getProperty("file.encoding"));

En un equipo puede ser UTF-8, en otro — Windows-1251, y en algún otro — ISO-8859-1. Por eso es mejor indicar siempre la codificación de forma explícita. Es especialmente importante si trabajas con datos multilingües, si los archivos se usarán en distintos ordenadores o se abrirán en otros programas, o si necesitas que tu código se comporte igual en cualquier entorno, y no solo en tu máquina.

Clase Charset: tu aliado en el mundo de las codificaciones

En Java, para trabajar con codificaciones se usa la clase java.nio.charset.Charset. Permite indicar la codificación por nombre (por ejemplo, "UTF-8") o utilizar constantes estándar (StandardCharsets.UTF_8).

Ejemplos de codificaciones estándar:

Codificación Constante de Java
UTF-8
StandardCharsets.UTF_8
UTF-16
StandardCharsets.UTF_16
ISO-8859-1
StandardCharsets.ISO_8859_1
Windows-1251
Charset.forName("Windows-1251")

Es preferible utilizar las constantes: hay menos probabilidades de equivocarse en el nombre y no aparecerá UnsupportedCharsetException.

2. Lectura de archivos indicando la codificación

Método antiguo:

import java.io.*;
import java.nio.charset.StandardCharsets;

BufferedReader reader = new BufferedReader(
    new InputStreamReader(
        new FileInputStream("example.txt"),
        StandardCharsets.UTF_8 // <-- Especificamos explícitamente la codificación
    )
);

Método moderno:

import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.io.BufferedReader;

BufferedReader reader = Files.newBufferedReader(
    Paths.get("example.txt"),
    StandardCharsets.UTF_8 // <-- Especificamos explícitamente la codificación
);

Se recomienda usar el segundo método — es más corto, más seguro y combina bien con try-with-resources.

Ejemplo: leer una línea de un archivo

try (BufferedReader reader = Files.newBufferedReader(
        Paths.get("hello.txt"),
        StandardCharsets.UTF_8)) {
    String line = reader.readLine();
    System.out.println("Leído: " + line);
}

Por qué es importante: Si el archivo se guardó en UTF-8 y lo lees como Windows-1251, los caracteres cirílicos se corromperán. Si indicas la codificación correcta, el texto se leerá correctamente en cualquier SO.

3. Escritura de archivos indicando la codificación

Método antiguo:

import java.io.*;
import java.nio.charset.StandardCharsets;

BufferedWriter writer = new BufferedWriter(
    new OutputStreamWriter(
        new FileOutputStream("example.txt"),
        StandardCharsets.UTF_8 // <-- Especificamos explícitamente la codificación
    )
);

Método moderno:

import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.io.BufferedWriter;

BufferedWriter writer = Files.newBufferedWriter(
    Paths.get("example.txt"),
    StandardCharsets.UTF_8 // <-- Especificamos explícitamente la codificación
);

Ejemplo: escribir una línea en un archivo

try (BufferedWriter writer = Files.newBufferedWriter(
        Paths.get("hello.txt"),
        StandardCharsets.UTF_8)) {
    writer.write("¡Hola, mundo!");
}

Resultado: El archivo se guardará en UTF-8, y se podrá abrir correctamente en cualquier editor que admita UTF-8.

4. Detalles útiles

Cómo conocer las codificaciones compatibles

import java.nio.charset.Charset;

public class ListCharsets {
    public static void main(String[] args) {
        System.out.println("Codificaciones disponibles:");
        Charset.availableCharsets().forEach((name, charset) -> System.out.println(name));
    }
}

Consejo: si utilizas una codificación exótica (por ejemplo, para ideogramas chinos antiguos o emoticonos marcianos), comprueba si tu JVM la admite.

Uso de try-with-resources: no olvides cerrar los flujos

Al trabajar con archivos, es importante cerrar los flujos para evitar fugas de recursos. El código Java moderno utiliza la construcción try-with-resources:

try (BufferedReader reader = Files.newBufferedReader(path, charset)) {
    // Trabajamos con el archivo
}

El flujo se cerrará automáticamente, incluso si ocurre un error.

Recomendaciones

  • Es mejor especificar siempre la codificación al leer y escribir archivos, incluso si estás seguro de que «por defecto todo funciona».
  • Usa UTF-8 para archivos nuevos — es el estándar de facto, especialmente si trabajas con web, JSON, XML, o quieres que tus archivos sean legibles en todas partes.
  • Para archivos antiguos (por ejemplo, exportaciones de 1C, bases de datos antiguas, CSV de Windows) usa la codificación en la que fueron guardados (por ejemplo, Windows-1251, ISO-8859-1).
  • No uses clases obsoletas donde la codificación no se especifica explícitamente: FileReader/FileWriter. En su lugar, utiliza InputStreamReader/OutputStreamWriter con codificación explícita o métodos de Files.
  • Para archivos grandes usa almacenamiento intermedio (BufferedReader/BufferedWriter) para no consumir toda la memoria.

5. Errores comunes al trabajar con codificaciones

Error n.º 1: No se especifica la codificación al leer/escribir el archivo.
Si no se indica la codificación, Java usa la del sistema por defecto ("file.encoding"). En tu máquina todo funciona, y en la de tu compañero — «caracteres raros».

Error n.º 2: No coinciden las codificaciones de lectura y escritura.
El archivo se guardó con una codificación y se lee con otra. Por ejemplo, el archivo se escribió en UTF-8 y se lee como Windows-1251 — la escritura cirílica se distorsiona.

Error n.º 3: Uso de las clases obsoletas FileReader/FileWriter.
Estas clases no permiten especificar la codificación de forma explícita — no se recomienda usarlas. En su lugar, usa InputStreamReader/OutputStreamWriter indicando la codificación o los métodos de Files.

Error n.º 4: Error en el nombre de la codificación.
Por ejemplo, escribiste "utf8" en lugar de "UTF-8" o "win1251" en lugar de "Windows-1251". Java lanzará UnsupportedCharsetException.

Error n.º 5: Flujo sin cerrar — el archivo no se escribió.
Si no usas try-with-resources o no cierras el flujo explícitamente, parte de los datos puede no llegar al disco.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION