CodeGym /Corsi /C# SELF /Problemi con le codifiche e

Problemi con le codifiche e BOM

C# SELF
Livello 37, Lezione 3
Disponibile

1. Perché con le codifiche è tutto così complicato?

Sai già che i file di testo sono solo una sequenza di byte. E C# (e .NET in generale) è una piattaforma che vuole che i caratteri stiano al loro posto. Sembra sufficiente specificare la codifica durante la lettura o la scrittura — e tutto dovrebbe funzionare. Ma il mondo reale è più complicato.

Motivi della confusione sulle codifiche:

  • Eredità storica: i file possono essere creati su diversi sistemi operativi e editor, ognuno con la sua codifica "di default".
  • Cross-platform: un file creato su Windows può essere letto su Linux o Mac, dove la codifica "di default" è diversa.
  • BOM (Byte Order Mark): una "testata" speciale del file che a volte c'è e a volte no. Influenza come i programmi interpretano il file.

2. Cos'è il BOM e a cosa serve

Breve su BOM

BOM (Byte Order Mark) è una sequenza speciale di byte all'inizio del file che dice al programma: "Ciao! Io sono in questa codifica, e così devi interpretare i miei byte".

  • BOM si trova più spesso nei file in UTF-8, UTF-16 e UTF-32.
  • In UTF-8 il BOM è opzionale. La sua presenza o assenza può influenzare come diversi programmi leggono il file.
Codifica BOM (rappresentazione esadecimale) Byte
UTF-8
EF BB BF
239 187 191
UTF-16 LE
FF FE
255 254
UTF-16 BE
FE FF
254 255
UTF-32 LE
FF FE 00 00
255 254 0 0
UTF-32 BE
00 00 FE FF
0 0 254 255

Verdetto dal tribunale delle codifiche: in ASCII e nelle codifiche ANSI il BOM non viene usato. Ma se compare, farà saltare tutte le vecchie applicazioni.

Illustrazione: dove si trova il BOM


+--------------------------+
| BOM |     TEXT BYTES     |
+--------------------------+
|EFBBBF|  48 65 6C 6C 6F   |  // "Hello" in UTF-8 con BOM
+--------------------------+

EF BB BF è il BOM per UTF-8. Sta all'inizio del file.
48 65 6C 6C 6F sono i byte del testo "Hello" in UTF-8 (senza BOM sarebbero uguali).
Insomma: il file inizia con EF BB BF, e poi viene il testo.

3. Mismatch di codifica: da dove nascono i caratteri illeggibili

Scenario tipico

  1. Salvi un file in UTF-8, ma senza BOM.
  2. Lo apri con un editor su Windows che si aspettava Windows-1251 o UTF-8 con BOM.
  3. Di conseguenza — invece di "Ciao, mondo!" vedi "Привет, РјРёСЂ!" (caratteri illeggibili).

Perché succede

  • Il programma pensa che il file sia in una codifica, mentre i byte sono in un'altra.
  • BOM aiuta a indovinare la codifica. Ma se il BOM manca, l'"indovinello" è pericoloso. Risultato: caratteri illeggibili.

Esempi di mismatch:

  • Leggi un file UTF-8 come Windows-1251 — tutti i caratteri non-ASCII diventano roba illeggibile.
  • Leggi un file UTF-8 con BOM come "puro" UTF-8 — spesso va bene, ma alcune vecchie app mostreranno i primi caratteri come segni strani.
  • Scrivi un file con BOM, ma chi lo consuma si aspetta che non ci sia — il software esterno che non gradisce il BOM può "inciampare".

4. Come la codifica e il BOM influenzano il lavoro con gli stream

Esempio: scrittura e lettura di file con codifiche diverse

// Scriviamo il file in UTF-8 con BOM
using var writer = new StreamWriter("test_utf8_bom.txt", false, new UTF8Encoding(true));
writer.WriteLine("Ciao, mondo!");

new UTF8Encoding(true) — include il BOM.

// Scriviamo il file in UTF-8 senza BOM
using var writer = new StreamWriter("test_utf8_no_bom.txt", false, new UTF8Encoding(false));
writer.WriteLine("Ciao, mondo!");

new UTF8Encoding(false) — senza BOM.

// Lettura del file specificando esplicitamente la codifica
using var reader = new StreamReader("test_utf8_no_bom.txt", new UTF8Encoding(false));
string line = reader.ReadLine();
Console.WriteLine(line);

Se il file è in UTF-8 senza BOM, specificare la codifica garantisce la lettura corretta.

Errore tipico

Quando non specifichi la codifica durante la lettura, StreamReader proverà a indovinare — prima controllerà il BOM, se presente; se non c'è, userà la codifica di sistema (su Windows spesso Windows-1251 per la versione russa, su Linux/Mac spesso UTF-8).

5. Cosa fare in caso di mismatch di codifica

Hai visto caratteri illeggibili. Cosa fare:

  1. Verifica con quale codifica è stato creato il file.
    Apri il file con un editor che mostra la codifica (es. Notepad++).
  2. Specifica esplicitamente la codifica durante la lettura/scrittura.
    Non fidarti del valore di default, anche se sembra che abbia sempre funzionato:
using var reader = new StreamReader("data.txt", Encoding.UTF8);

Fai attenzione al BOM.

  • Se un altro software richiede il BOM — aggiungilo (vedi new UTF8Encoding(true)).
  • Se non è richiesto — scrivi senza BOM (vedi new UTF8Encoding(false)).

Esempio: lettura con codifica sbagliata

// Il file è creato in UTF-8, lo leggiamo come Windows-1251
using var reader = new StreamReader("test_utf8_no_bom.txt", Encoding.GetEncoding(1251));
var text = reader.ReadToEnd();
Console.WriteLine(text); // "Ciao, mondo!" verrà corrotto

6. Note utili

BOM nei progetti reali e nei colloqui

Se lavori su un progetto dove devi salvare config, log o esportare dati, conviene decidere subito la codifica e documentarla. Può sembrare una sciocchezza, ma quando quei file vengono letti da altri programmi o persone, malintesi sulla codifica portano a molti problemi.

Nei colloqui il tema del BOM e dei "caratteri strani all'inizio del file" è quasi un argomento richiesto. È importante non solo sapere cos'è il BOM, ma saper spiegare perché la sua presenza (o assenza) influisce sulle integrazioni e come questo è collegato alla codifica esplicita.

Presta particolare attenzione allo scambio con sistemi esterni su altri OS o scritti in altri linguaggi. In alcuni posti il BOM è obbligatorio, in altri rompe il parsing. Se non lo prevedi, i problemi saranno difficili da diagnosticare.

Raccomandazioni e migliori pratiche

  • Specifica esplicitamente la codifica quando lavori con file (non affidarti mai al default).
  • Se serve il BOM — usa new UTF8Encoding(true), se no — new UTF8Encoding(false).
  • Controlla i file con editor che supportano più codifiche (ad esempio Notepad++, Visual Studio Code).
  • Se ricevi un file dall'esterno — chiedi ai colleghi o consulta la documentazione per sapere in quale codifica è stato creato.
  • Se devi convertire la codifica o rimuovere il BOM — fallo in modo esplicito.

Cosa vedono i diversi programmi

File Codifica di scrittura Apri come Cosa vediamo
UTF-8 con BOM
UTF-8 + BOM
UTF-8
OK ("Ciao, mondo!")
UTF-8 senza BOM
UTF-8
Windows-1251
Caratteri illeggibili
Win-1251
Win-1251
UTF-8
Caratteri illeggibili
UTF-8 con BOM
UTF-8 + BOM
ASCII
I primi byte sono corrotti

7. Come verificare e rimuovere il BOM

Esempio: verificare la presenza del BOM

byte[] bytes = File.ReadAllBytes("test_utf8_bom.txt");
// Controlliamo i primi 3 byte
if (bytes.Length >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF)
{
    Console.WriteLine("BOM trovato! È UTF-8 con BOM.");
}
else
{
    Console.WriteLine("BOM assente.");
}

Esempio: rimuovere il BOM (se per qualche motivo dà fastidio)

if (bytes.Length >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF)
{
    // Scriviamo il file senza i primi 3 byte
    File.WriteAllBytes("no_bom.txt", bytes.Skip(3).ToArray());
}

8. Errori tipici e come risolverli

Molti sviluppatori alle prime armi si stupiscono quando il loro programma inizia a "impazzire" con i file di testo. Di solito il problema è che il programma che ha scritto il file ha usato una codifica (o un'impostazione di BOM) diversa da quella che lo legge. Per esempio, se scrivi in UTF-8 senza BOM, e lo leggi su Windows dove la codifica di sistema è Windows-1251, non c'è da meravigliarsi se i caratteri diventano illeggibili. È fondamentale specificare sempre esplicitamente la codifica. Se il file deve essere scambiato tra piattaforme o programmi diversi, usa un formato universale — UTF-8 (o UTF-8 con BOM, solo se richiesto dal software esterno).

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