Možná si říkáte proč o tomhle psát příspěvek, když je to v .NETu záležitost na dva řádky. Konktrétně tedy volání metod System.IO.File.ReadAllText a System.IO.File.WriteAllText. Problém ale nastává, pokud je potřeba zachovat encoding souboru takový jako má původní soubor. Výše dvě metody totiž pracují buď s encodingem, který se předá parametrem, anebo natvrdo s System.Text.Encoding.UTF8.
Pokud tedy potřebujeme při čtení souboru nejprve zjistit jeho encoding a ten pak použít při jeho zápisu, je kód o něco složitější. Celé si to ukážeme na příkladu, následující kód načte textový soubor do stringu, poté provede záměnu znaku '*’ na ‘?’ a poté soubor uloží zpět (přepíše původní soubor).
private void ChangeFile()
{
string filePath = @"C:\Soubor.txt";
//Read file
Encoding fileEncoding;
string content;
using (StreamReader reader = new StreamReader(filePath, Encoding.Default))
{
content = reader.ReadToEnd();
fileEncoding = reader.CurrentEncoding;
}
//Change content
content = content.Replace('*', '?');
//Ensure that the file is writeable
FileAttributes fileAttributes = File.GetAttributes(filePath);
File.SetAttributes(filePath, fileAttributes & ~FileAttributes.ReadOnly);
//Save to file
File.WriteAllText(filePath, content, fileEncoding);
//Restore the file's original attributes
File.SetAttributes(filePath, fileAttributes);
}
Ke čtení souboru použijeme StreamReader, na vlastní čtení použijeme volání ReadToEnd. To samé by udělala i metoda ReadAllText, navíc ale můžeme z StreamReader vlastností CurrentEncoding zjistit encoding, který se detekuje podle obsahu souboru čtením. Pozor tedy, že vlastnost CurrentEncoding je nutné načíst až po volání ReadToEnd.
Další důležitou věcí, je to, že při volání konstruktoru třídy StreamReader je nutné uvést encoding, který bude vrácen v případě že encoding není v souboru uložen (a nelze tedy zjistit). To nastane v případě souboru uloženého v ANSI formátu. Já tedy při volání použiju Encoding.Default to je u nás Windows-1250. Pokud encoding nelze ze souboru zjistit a v konstruktoru by se tato hodnota neurčila, vracela by vlastnost CurrentEncoding špatně hodnotu Encoding.UTF8.
V další části kódu se provede vlastní replace textu a pak uložení souboru. Aby byl příklad o něco složitější, přidal jsem ještě logiku na zrušení a po uložení opětovné nahození atributu ReadOnly.