Načtení a uložení textového souboru

Jan Holan       19. 1. 2011       I/O operace       8140 zobrazení

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.

 

hodnocení článku

0 bodů / 1 hlasů       Hodnotit mohou jen registrované uživatelé.

 

Nový příspěvek

 

RE: Načtení a uložení textového souboru

Jen doplním upřesňující vysvětlení:

Textové soubory jsou na disku uložené úplně stejně jako soubory binární tj. jako obyčejná sekvence bajtů. Rozdíl je pouze v tom, že u textového souboru tato sekvence podléhá určitým pravidlům pro kódování textu tj. určitému encodingu, ve kterém je konkrétní soubor uložen. Při otevření/načtení textového souboru se proto musí vědět jaký encoding použít pro zpětný převod na text.

Zde zafunguje jedna ze tří možností: Buď je v souboru ještě před vlastním textem uložena speciální sekvence bajtů (preamble), která je jedinečná pro daný encoding tj. pokud se tato sekvence najde, vynechá se a dále se použije určený encoding (např. u UTF-8). Nebo se z toho jak je sekvence bajtů „stavěna“ dá rozpoznat o jaký encoding se jedná (např. u Unicode). Tyto dvě věci se provádějí vždy, když je nepotlačíme explicitním nastavením parametru detectEncodingFromByteOrderMarks na hodnotu false v konstruktoru třídy StreamReader. Pokud toto selže, použije se jednoduše určený encoding (např. v konstruktoru třídy StreamReader) nebo encoding UTF-8 jako výchozí.

Dále se ještě využívá toho, že některé encodingy jsou dost podobné, takže např. pokud v textovém souboru nejsou žádné speciální znaky (a pouze u těch se nejčastěji encoding liší) tak se může soubor korektně načíst i pokud se na začátku určil encoding chybně. Toto nám však nemusí pomoct, pokud potřebujeme změněný soubor uložit v přesně stejném encodingu jako byl před změnou.

A ještě poslední poznámka, uvedl jsem, že u většiny operací s textovými soubory je implicitně jako výchozí encoding nastaven UTF-8, neplést však s Encoding.Default - to je ANSI encoding, který odpovídá aktuální kódové stránce Windows tedy u nás např. „Central European (Windows) – Codepage 1250“.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback