CodeGym /Cursos /JAVA 25 SELF /Definindo a codificação ao ler/gravar arquivos

Definindo a codificação ao ler/gravar arquivos

JAVA 25 SELF
Nível 37 , Lição 2
Disponível

1. Introdução

Vamos ser diretos: se você alguma vez viu, no lugar de texto em russo, algo como Привет, você já foi vítima de uma codificação incorreta. Isso acontece quando um arquivo foi gravado em uma codificação e lido em outra. Por exemplo, o arquivo foi salvo como UTF-8, mas é lido como Windows-1251, ou vice-versa.

Por padrão, o Java usa a codificação do sistema, que pode ser obtida assim:

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

Em um computador isso pode ser UTF-8, em outro — Windows-1251, e em algum outro — ISO-8859-1. Por isso é sempre melhor especificar a codificação explicitamente. Isso é especialmente importante se você precisa trabalhar com dados multilíngues, se os arquivos serão usados em diferentes computadores ou abertos em outros programas, ou se você precisa que seu código se comporte de forma consistente em qualquer ambiente, não apenas na sua máquina.

Classe Charset: seu aliado no mundo das codificações

No Java, para trabalhar com codificações usa-se a classe java.nio.charset.Charset. Ela permite definir a codificação pelo nome (por exemplo, "UTF-8") ou usar as constantes padrão (StandardCharsets.UTF_8).

Exemplos de codificações padrão:

Codificação Constante Java
UTF-8
StandardCharsets.UTF_8
UTF-16
StandardCharsets.UTF_16
ISO-8859-1
StandardCharsets.ISO_8859_1
Windows-1251
Charset.forName("Windows-1251")

É preferível usar as constantes: menor chance de errar o nome e você não terá uma UnsupportedCharsetException.

2. Leitura de arquivos especificando a codificação

Maneira antiga:

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

BufferedReader reader = new BufferedReader(
    new InputStreamReader(
        new FileInputStream("example.txt"),
        StandardCharsets.UTF_8 // <-- Indicamos explicitamente a codificação
    )
);

Maneira moderna:

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

BufferedReader reader = Files.newBufferedReader(
    Paths.get("example.txt"),
    StandardCharsets.UTF_8 // <-- Indicamos explicitamente a codificação
);

Recomenda-se usar a segunda maneira — ela é mais curta, mais segura e combina bem com try-with-resources.

Exemplo: ler uma linha do arquivo

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

Por que isso é importante: Se o arquivo foi salvo em UTF-8 e você o lê como Windows-1251, os caracteres cirílicos ficarão corrompidos. Ao informar a codificação correta, o texto será lido corretamente em qualquer SO.

3. Gravação de arquivos especificando a codificação

Maneira antiga:

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

BufferedWriter writer = new BufferedWriter(
    new OutputStreamWriter(
        new FileOutputStream("example.txt"),
        StandardCharsets.UTF_8 // <-- Indicamos explicitamente a codificação
    )
);

Maneira moderna:

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

BufferedWriter writer = Files.newBufferedWriter(
    Paths.get("example.txt"),
    StandardCharsets.UTF_8 // <-- Indicamos explicitamente a codificação
);

Exemplo: escrever uma linha no arquivo

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

Resultado: O arquivo será salvo em UTF-8 e poderá ser aberto corretamente em qualquer editor que suporte UTF-8.

4. Dicas úteis

Como descobrir as codificações suportadas

import java.nio.charset.Charset;

public class ListCharsets {
    public static void main(String[] args) {
        System.out.println("Codificações disponíveis:");
        Charset.availableCharsets().forEach((name, charset) -> System.out.println(name));
    }
}

Dica: Se você estiver usando uma codificação exótica (por exemplo, para ideogramas chineses antigos ou emojis marcianos), verifique se ela é suportada pela sua JVM.

Usando try-with-resources: não se esqueça de fechar os streams

Ao trabalhar com arquivos, é importante fechar os streams para evitar vazamentos de recursos. O código Java moderno usa a construção try-with-resources:

try (BufferedReader reader = Files.newBufferedReader(path, charset)) {
    // Trabalhando com o arquivo
}

O stream será fechado automaticamente, mesmo se ocorrer um erro.

Recomendações

  • É melhor sempre especificar explicitamente a codificação ao ler e gravar arquivos, mesmo que você tenha certeza de que “por padrão tudo funciona”.
  • Use UTF-8 para novos arquivos — é o padrão de fato, especialmente se você trabalha com web, JSON, XML, ou quer que seus arquivos sejam legíveis em qualquer lugar.
  • Para arquivos antigos (por exemplo, exportações do 1C, bancos de dados antigos, CSV do Windows), use a codificação em que foram salvos (por exemplo, Windows-1251, ISO-8859-1).
  • Não use classes obsoletas nas quais a codificação não é definida explicitamente: FileReader/FileWriter. Em vez delas, use InputStreamReader/OutputStreamWriter com codificação explícita ou os métodos de Files.
  • Para arquivos grandes use bufferização (BufferedReader/BufferedWriter) para não consumir toda a memória.

5. Erros comuns ao trabalhar com codificações

Erro nº 1: A codificação não é especificada ao ler/gravar o arquivo.
Se você não especificar a codificação, o Java usará a do sistema por padrão ("file.encoding"). Na sua máquina tudo funciona, mas na do colega — aparece “mojibake”.

Erro nº 2: As codificações de leitura e gravação não coincidem.
O arquivo foi gravado em uma codificação e lido em outra. Por exemplo, o arquivo foi gravado em UTF-8, mas é lido como Windows-1251 — os caracteres cirílicos ficam corrompidos.

Erro nº 3: Uso das classes obsoletas FileReader/FileWriter.
Essas classes não permitem especificar a codificação explicitamente — não é recomendado usá-las. Em vez delas, use InputStreamReader/OutputStreamWriter informando a codificação ou os métodos de Files.

Erro nº 4: Nome da codificação incorreto.
Por exemplo, você escreveu "utf8" em vez de "UTF-8" ou "win1251" em vez de "Windows-1251". O Java lançará UnsupportedCharsetException.

Erro nº 5: Stream não fechado — o arquivo não foi gravado.
Se você não usar try-with-resources ou não fechar o stream explicitamente, parte dos dados pode não ser gravada no disco.

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION