CodeGym /Corsi /JAVA 25 SELF /Impostazione della codifica durante la lettura/scrittura ...

Impostazione della codifica durante la lettura/scrittura dei file

JAVA 25 SELF
Livello 37 , Lezione 2
Disponibile

1. Introduzione

Diciamolo subito: se almeno una volta avete visto al posto del testo in russo qualcosa come Привет, siete già vittime di una codifica errata. Succede quando un file è stato scritto con una codifica e viene letto con un'altra. Per esempio, il file è stato salvato come UTF-8 ma viene letto come Windows-1251, o viceversa.

Java per impostazione predefinita usa la codifica di sistema, che si può ottenere così:

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

Su un computer può essere UTF-8, su un altro — Windows-1251, e altrove — ISO-8859-1. Per questo motivo è sempre meglio specificare esplicitamente la codifica. È particolarmente importante se lavorate con dati multilingue, se i file verranno usati su computer diversi o aperti in altri programmi, o se volete che il vostro codice si comporti allo stesso modo in qualsiasi ambiente, e non solo sulla vostra macchina.

La classe Charset: il vostro alleato nel mondo delle codifiche

In Java per lavorare con le codifiche si usa la classe java.nio.charset.Charset. Permette di specificare la codifica per nome (ad esempio, "UTF-8") oppure di usare le costanti standard (StandardCharsets.UTF_8).

Esempi di codifiche standard:

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

È preferibile usare le costanti: meno probabilità di sbagliare il nome e non si verificherà UnsupportedCharsetException.

2. Lettura dei file con specifica della codifica

Metodo vecchio:

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

BufferedReader reader = new BufferedReader(
    new InputStreamReader(
        new FileInputStream("example.txt"),
        StandardCharsets.UTF_8 // <-- Specifichiamo esplicitamente la codifica
    )
);

Metodo 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 // <-- Specifichiamo esplicitamente la codifica
);

Si consiglia di usare il secondo approccio — è più conciso, più sicuro e si integra bene con try-with-resources.

Esempio: leggiamo una riga da un file

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

Perché è importante: Se il file è stato salvato in UTF-8 ma lo leggete come Windows-1251, i caratteri cirillici verranno distorti. Specificando la codifica corretta, il testo verrà letto correttamente su qualsiasi sistema operativo.

3. Scrittura dei file con specifica della codifica

Metodo vecchio:

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

BufferedWriter writer = new BufferedWriter(
    new OutputStreamWriter(
        new FileOutputStream("example.txt"),
        StandardCharsets.UTF_8 // <-- Specifichiamo esplicitamente la codifica
    )
);

Metodo 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 // <-- Specifichiamo esplicitamente la codifica
);

Esempio: scriviamo una riga in un file

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

Risultato: Il file verrà salvato in UTF-8 e potrà essere aperto correttamente in qualsiasi editor che supporti UTF-8.

4. Dettagli utili

Come scoprire le codifiche supportate

import java.nio.charset.Charset;

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

Consiglio: Se usate una codifica esotica (ad esempio per ideogrammi cinesi antichi o per faccine marziane), verificate che sia supportata dalla vostra JVM.

Uso di try-with-resources: non dimenticare di chiudere gli stream

Quando si lavora con i file, è importante chiudere gli stream per evitare perdite di risorse. Il codice Java moderno usa la costruzione try-with-resources:

try (BufferedReader reader = Files.newBufferedReader(path, charset)) {
    // Lavoriamo con il file
}

Lo stream verrà chiuso automaticamente, anche se si verifica un errore.

Raccomandazioni

  • Meglio specificare sempre esplicitamente la codifica durante la lettura e la scrittura dei file, anche se siete sicuri che «di default funziona tutto».
  • Usate UTF-8 per i nuovi file — è lo standard de facto, soprattutto se lavorate con il web, JSON, XML, o se volete che i vostri file siano leggibili ovunque.
  • Per i file legacy (ad esempio, esportazioni da 1C, vecchi database, CSV da Windows) usate la codifica con cui sono stati salvati (ad esempio, Windows-1251, ISO-8859-1).
  • Non usate classi obsolete, in cui la codifica non è specificata esplicitamente: FileReader/FileWriter. Al loro posto utilizzate InputStreamReader/OutputStreamWriter con codifica esplicita oppure i metodi di Files.
  • Per file grandi usate la bufferizzazione (BufferedReader/BufferedWriter) per non esaurire tutta la memoria.

5. Errori tipici nella gestione delle codifiche

Errore n. 1: codifica non specificata durante la lettura/scrittura del file.
Se non si specifica la codifica, Java usa quella di sistema predefinita ("file.encoding"). Sulla vostra macchina tutto funziona, ma su quella del collega — caratteri illeggibili.

Errore n. 2: mancata corrispondenza tra codifiche in lettura e scrittura.
Il file è stato scritto con una codifica, ma viene letto con un'altra. Ad esempio, il file è scritto in UTF-8 ma viene letto come Windows-1251 — i caratteri cirillici risultano alterati.

Errore n. 3: uso delle classi obsolete FileReader/FileWriter.
Queste classi non permettono di specificare esplicitamente la codifica — il loro uso è sconsigliato. Al loro posto usate InputStreamReader/OutputStreamWriter indicando la codifica oppure i metodi di Files.

Errore n. 4: errore nel nome della codifica.
Per esempio, avete scritto "utf8" invece di "UTF-8" o "win1251" invece di "Windows-1251". Java genererà UnsupportedCharsetException.

Errore n. 5: stream non chiuso — file non scritto.
Se non si usa try-with-resources o non si chiude esplicitamente lo stream, una parte dei dati potrebbe non essere scritta su disco.

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