Práce s obsahem souborů v .NET

Jedním z námětů, které jsem obdržel v rámci své výzvy ptejte se mne na co chcete, já na co chci odpovím, byla žádost o vysvětlení práce s textovými soubory. Zadání jsem si rozšířil na práci s obsahem souborů obecně - nebo chcete-li se streamy.

Co je stream

Většina vstupně/výstupních operací se v .NET děje prostřednictvím nějaké formy streamu. Stream představuje obecně jakýkoliv objekt, ze kterého lze číst nebo do něj zapisovat bajty. Tato abstrakce je velmi široce použitelná: v tomto článku se budu zabývat toliko soubory, ale tentýž přístup je možno aplikovat na TCP/IP síťové spojení, komunikaci přes sériový port, kryptografické operace a řadu dalších věcí.

Základní třídou je v tomto případě System.IO.Stream. Jeho základní metody jsou ReadByte, Read, WriteByte a Write. Ty umožňují přečíst nebo zapsat jeden či více bajtů. Steam může umožňovat čtení, zápis nebo obojí. To lze zjistit z vlastností CanRead a CanWrite. Metodou Close lze stream zavřít (a v případě souborů zapsat provedené změny na disk).

Tato třída je abstraktní a musí být tedy v praxi implementována pomocí specializovaných tříd jako je například FileStream, NetworkStream nebo MemoryStream.

Textové soubory

Možnosti samotného streamu nejsou moc velké. Zapsat nebo přečíst hromádku bajtů sice v zásadě stačí, ale pro praktickou práci by bylo potřeba napsat spoustu věcí okolo. Pro práci s textovými soubory proto .NET obsahuje třídy System.IO.StreamReader a System.IO.StreamWriter. Ty umožňují pohodlně ze streamu číst nebo do něj zapisovat řetězcová data v požadovaném kódování. Disponují přitom metodami jako ReadLine nebo WriteLine, které umožňují zpracování souboru po řádcích.

Následující kód tedy vytvoří textový soubor a zapíše do něj dva řádky textu:

Dim Soubor As New System.IO.StreamWriter(Server.MapPath("/StreamDemo/demo.txt"))
Soubor.WriteLine("První řádek")
Soubor.WriteLine("Druhý řádek")
Soubor.Close()

Vcelku podobným způsobem je možno soubor i číst. Zde se uplatní též metoda Peek. Ta "nakoukne" na další bajt v souboru a aniž by posunula pomyslný kurzor, vrátí jeho hodnotu. V případě, že narazí na konec souboru, vrátí -1. Toho lze s úspěchem využít při řešení úloh typu "načítej dokud nenarazíš na konec souboru. Následující kód přečte po řádcích obsah zdrojového souboru a vypíše ho na výstup:

Dim Soubor As New System.IO.StreamReader(Server.MapPath("/StreamDemo/demo.txt"))
Do While Soubor.Peek() > -1
    Dim Radek As String = Soubor.ReadLine()
    Response.Write(Radek & "<br>")
Loop
Soubor.Close()

V tomto konkrétním případě je víceméně zbytečné číst soubor po řádcích. Mnohem jednodušší by bylo použít metodu ReadToEnd a poté prostě nahradit konce řádků tagem <br>.

Různá kódování

.NET Framework vnitřně pracuje se všemi daty v kódování UNICODE, resp. UTF-8. I jeho výše uvedené třídy tedy implicitně předpokládají, že veškerá data jsou k dispozici v UTF-8. Ačkoliv vám vřele doporučuji, aby vaše programy tuto logiku přejaly (ušetříte si tím spoustu práce a problémů), může se stát, že data dostanete v kódování jiném.

Ani to nepředstavuje zásadní problém. Obšírnější pojednání o kódování řetězců v .NET jsem napsal již před časem, detaily si přečtěte v něm. Pro účely čtení nebo zápisu pomocí StreamReaderu a StreamWriteru stačí prostě požadované kódování specifikovat jako další volitelný parametr. Máte-li tedy vstupní data například v kódování Windows 1250, stačí příslušný řádek modifikovat takto:

Dim Soubor As New System.IO.StreamReader(Server.MapPath("/StreamDemo/demo.txt"), _
                  System.Text.Encoding.GetEncoding("Windows-1250"))

Pohodlný přístup

V příkladech výše jsem soubory volal přímo pomocí odpovídajícího StreamReaderu či StreamWriteru. Zcela stejných výsledků, někdy pohodlnější cestou, lze dosíci použitím rozličných statických metod v System.IO.File. Například CreateText, AppendText a OpenText.

Titulek:
Text komentáře:
Vaše jméno:
Váš e-mail: (nebude zveřejněn)

WWW stránka:
Opište text z obrázku:
odpovědětodpovědět Gravatar

Dotaz

31.1.2005 11:45:2431.1.2005 11:45:24 MartinMartin ---.plzen-city.cz

Jakym zpusobem naplnim promenou retezcem z textoveho souboru.Napr. 3 radek 3-5 znak.

odpovědětodpovědět Gravatar

Kolize pri manipulaci se souborem.

8.4.2005 3:47:448.4.2005 3:47:44 LeonineLeonine ---.net.upc.cz

Rad bych se optal, zda-li je takovyto postup chraneny proti kolizi v pripade ze je ze souboru cteno a zapisovano ve stejnou dobu? A popr. jak takove kolizi predchazet. Jako priklad bych uvedl jednoduchou webovou aplikaci typu chat. Kdy muze snadno nastat vise zminena situace.

Predem Dekuji za jakekoliv odpovedi na dane tema.

odpovědětodpovědět Gravatar

RE: Kolize pri manipulaci se souborem.

Záleží na typu současně prováděných operací. Obecně se dá říci, že to proti kolizím chráněno není. Pokud takovou funkci vyžadujete, musíte si ji napsat sami.

A nebo použít pro daný účel vhodnější úložiště dat, třeba relační databázi.

  • Altairis
  • Nemesis
  • Microsoft MVP
  • IIS
  • ASP.NET