1. Introduzione
Iniziamo dalla domanda principale — perché preoccuparsi delle codifiche? Potrebbe sembrare che un file, una codifica e tutto dovrebbe andare liscio. Ma nella realtà le cose sono molto più interessanti. Si scopre presto che un file può arrivare da qualsiasi parte e in una codifica del tutto inaspettata. E la tua applicazione, ovviamente, ne aspetta un'altra.
A volte devi integrarti con qualche API o sistema che impone rigidamente: solo una certa codifica e nient'altro. Capita anche di tirare fuori un file vecchio di dieci anni e provarlo ad aprire in un editor moderno — e vedi krakozyabry. Oppure, ad esempio, salvi un report CSV e vuoi essere sicuro che tutti i colleghi lo leggano correttamente — su Windows, su Mac e persino in Excel.
Insomma, la ricodifica non è qualcosa di raro o esotico. È invece un compito molto reale e abbastanza frequente che emerge ovunque: esportazioni da DB, lavoro con archivi, integrazione con contabilità o script automatici. E prima ti ci metti, meno sorprese avrai dopo.
Dalla codifica vecchia a quella nuova
Per ricodificare un file bisogna fare due passi:
- Leggere il file nella codifica di origine, ottenendo stringhe (o caratteri).
- Scrivere le stringhe in un nuovo file, specificando esplicitamente la codifica di destinazione desiderata.
Analogia: immagina di tradurre un libro dal francese al russo. Prima devi saper leggere il francese (leggere il testo), poi esprimere lo stesso senso in russo (scrivere il testo in russo).
In C# (e .NET) questo si realizza impostando l'oggetto appropriato Encoding nel costruttore di StreamReader (per la lettura) e StreamWriter (per la scrittura).
Panoramica delle codifiche e la classe Encoding
Tutte le trasformazioni "magiche" dei caratteri sono effettuate tramite la classe System.Text.Encoding.
Una tabella con le codifiche principali e come ottenerle in C# può essere così rappresentata:
| Codifica | Descrizione | Costante C# |
|---|---|---|
| UTF-8 | Universale, senza BOM per default | |
| UTF-8 con BOM | Stessa cosa, ma con la signature BOM | |
| UTF-16 (LE/BE) | "Wide char", little-endian | Encoding.Unicode (LE), Encoding.BigEndianUnicode (BE) |
| ASCII | Classico a 7 bit | |
| Windows-1251 | Popolare per il cirillico | |
| ISO-8859-1 | Latino (europeo) | |
Nota: Per codifiche più vecchie dovrai usare Encoding.GetEncoding, a volte con il numero (1251), a volte con la stringa ("windows-1251").
2. Ricodifica: strategia passo-passo in C#
Vediamo come realizzare la ricodifica nella pratica.
Algoritmo
- Aprire il file sorgente tramite StreamReader, specificando esplicitamente la codifica iniziale.
- Leggere il testo (o tutto in una volta, o riga per riga — dipende dalla dimensione del file).
- Aprire il file di destinazione tramite StreamWriter, specificando la codifica finale voluta.
- Scrivere il testo nel file di destinazione.
- Non dimenticare di chiudere gli stream — usiamo using per sicurezza!
Esempio: ricodifica Windows-1251 → UTF-8
Supponiamo di avere un file "input-1251.txt" in codifica Windows-1251 e di volerne uno "output-utf8.txt" in UTF-8 "pulito" (senza BOM).
// Specifichiamo la sorgente con la codifica iniziale
using var reader = new StreamReader("input-1251.txt", Encoding.GetEncoding(1251));
using var writer = new StreamWriter("output-utf8.txt", false, Encoding.UTF8);
string line;
// Leggiamo riga per riga — comodo per file grandi
while ((line = reader.ReadLine()) != null)
{
writer.WriteLine(line);
}
Console.WriteLine("File ricodificato da Windows-1251 a UTF-8 con successo!");
Questo codice garantisce che ogni riga venga correttamente convertita da una codifica all'altra.
Schematizzato è così:
┌───────────────────────────────┐ ┌───────────────────┐ ┌───────────────────────────────┐
│ File "input-1251.txt" (1251) │ --> │ StreamReader │ --> │ String di tipo string in memoria │
└───────────────────────────────┘ │ (Encoding 1251) │ └───────────────────────────────┘
└───────────────────┘
│
▼
┌────────────────────────┐
│ StreamWriter │
│ (Encoding UTF-8) │
└───────────┬────────────┘
│
▼
┌──────────────────────────────┐
│ "output-utf8.txt" (UTF-8) │
└──────────────────────────────┘
3. Esempio pratico: converter di codifiche
Complichiamo un po': scriviamo un semplice programma-converter dove l'utente sceglie file sorgente e destinazione e le codifiche.
Console.WriteLine("Inserisci il percorso del file sorgente:");
string inputPath = Console.ReadLine();
Console.WriteLine("Codifica del file sorgente (ad esempio, 1251, utf-8):");
string sourceEncodingName = Console.ReadLine();
Console.WriteLine("Inserisci il percorso del file di destinazione:");
string outputPath = Console.ReadLine();
Console.WriteLine("Codifica per il salvataggio (ad esempio, utf-8, 1251):");
string destEncodingName = Console.ReadLine();
Encoding sourceEncoding = Encoding.GetEncoding(sourceEncodingName);
Encoding destEncoding = Encoding.GetEncoding(destEncodingName);
using var reader = new StreamReader(inputPath, sourceEncoding);
using var writer = new StreamWriter(outputPath, false, destEncoding);
string line;
while ((line = reader.ReadLine()) != null)
{
writer.WriteLine(line);
}
Console.WriteLine("Fatto! Controlla il risultato.");
Consiglio: Se non sei sicuro di quale codifica usare, consulta la documentazione o prova varie opzioni. A volte un file si può "identificare" solo sperimentalmente, se nessuno ha lasciato un README gentile.
4. Aspetti importanti: BOM, caratteri "invisibili" e casi speciali
Come aggiungere il BOM quando si salva in UTF-8?
Per default Encoding.UTF8 in C# crea file senza BOM (Byte Order Mark). Se vuoi creare un file con BOM, usa:
// true — significa "con BOM"
var utf8WithBom = new UTF8Encoding(true);
using var writer = new StreamWriter("with-bom.txt", false, utf8WithBom);
writer.WriteLine("Testo con BOM");
Il file ora inizierà con tre byte "invisibili": 0xEF, 0xBB, 0xBF.
Quando il BOM è male?
- Se esporti CSV per Excel, nella maggior parte delle versioni straniere il BOM infastidisce — compaiono caratteri strani.
- Nei sistemi Unix-like (Linux) il BOM a volte rovina l'elaborazione dei file.
- Per i file JSON il BOM è quasi sempre male, molti parser non lo sopportano!
Consiglio: Scegli consapevolmente se hai bisogno del BOM e "aggiungilo" solo quando serve.
Caratteri nascosti e numeri magici
Se all'apertura del file ricodificato l'applicazione segnala errore di formato, potrebbe essere che non hai considerato caratteri "invisibili" all'inizio del file (ad esempio il BOM), o che hai sbagliato la codifica stessa (ad esempio hai letto come ASCII mentre lì c'è cirillico in 1251). Controlla sempre quali codifiche usa la tua app/collega/server.
5. Suggerimenti utili
Lavorare con file grandi: perché riga per riga e non tutto insieme?
Si potrebbe fare semplicemente:
string allText = File.ReadAllText("input.txt", Encoding.GetEncoding(1251));
File.WriteAllText("output.txt", allText, Encoding.UTF8);
Questo va bene per file piccoli e medi (diciamo fino a 50 MB). Ma se il file è grande, l'intero testo verrà caricato in RAM — e se il file è di qualche GB sarà "oops". Per universalità usiamo la lettura/scrittura riga per riga.
Ricodifica tra codifiche meno comuni
Supponiamo che tu abbia un file in ISO-8859-1 (i DB MySQL lo adorano), e tu debba ottenerlo in Unicode.
var sourceEnc = Encoding.GetEncoding("iso-8859-1");
var destEnc = Encoding.UTF8;
using var reader = new StreamReader("data-latin.txt", sourceEnc);
using var writer = new StreamWriter("data-unicode.txt", false, destEnc);
string line;
while ((line = reader.ReadLine()) != null)
{
writer.WriteLine(line);
}
Questo approccio funziona con qualsiasi codifica supportata da .NET.
Non fare ricodifica di file binari!
Il programma descritto sopra è pensato esclusivamente per file di testo. Se il file è binario (per esempio un'immagine, un file audio, un archivio), provare a "leggerlo come testo e poi riscriverlo" taglierà i byte, produrrà un sacco di krakozyabry e il file non funzionerà più. Per file binari la "codifica" non ha senso.
Tabella di mapping: quando usare quale codifica
| Codifica | Quando usare |
|---|---|
| UTF-8 | File universali, web, applicazioni moderne |
| UTF-8 con BOM | Per compatibilità con Notepad, Excel |
| Windows-1251 | Per "vecchia scuola", programmi locali in russo |
| ASCII | Per file con solo testo inglese |
| UTF-16 | Per casi speciali, applicazioni esotiche |
Trucchi e consigli
Come capire la codifica di un file?
- Editor specializzati (Notepad++, Visual Studio Code) spesso rilevano e mostrano la codifica.
- Se non c'è BOM e tutto sembra "leggibile" ma i caratteri sono sbagliati — probabilmente la codifica non corrisponde.
Si può automatizzare il rilevamento della codifica?
- In .NET non esiste una "bacchetta magica" che individuI al 100% la codifica di qualsiasi file. Di solito: se c'è BOM è chiaramente UTF con BOM, se non c'è devi indovinare dal contenuto o provare varie opzioni.
Cosa fare se alcune righe si leggono bene e altre hanno "krakozyabry"?
- Forse il file è "composito" o corrotto. Verifica se non è stato scritto da programmi diversi con codifiche differenti.
6. Errori tipici e come evitarli
Per chiarire, vediamo gli errori più comuni:
Codifica di partenza sbagliata. Se pensi che il file sia UTF-8 ma in realtà è Windows-1251 — otterrai "scale" al posto del cirillico. Controlla la codifica di origine; se non sei sicuro apri con Notepad++ o editor simili che mostrano la codifica reale.
BOM nel posto sbagliato. A volte aggiungere il BOM rompe il parsing, altre volte l'assenza del BOM impedisce ad altri software di rilevare la codifica corretta.
Caricare tutto il file in memoria. Per file grandi usa la lettura riga per riga — altrimenti il programma "mangerà" tutta la RAM su basi di testo grandi.
Scrivere senza specificare la codifica. Per default StreamWriter usa UTF-8 senza BOM. Se vuoi un'altra variante — specifica esplicitamente la codifica.
Uso scorretto di GetEncoding. Se sbagli la stringa, per esempio "utf8" invece di "utf-8", otterrai un'eccezione. Usa nomi corretti (o codici, per esempio 1251).
GO TO FULL VERSION