Adatfolyamok kezelése ([FileStream], [MemoryStream])

Gyakran előfordul, hogy az adathalmazunkat nem akarjuk egy egységként kezelni, hanem ahogy jönnek az elemi adatok, azokat folyamatosan szeretnénk feldolgozni. Ezen feldolgozásra a fájl és memória adatfolyamok (stream) állnak rendelkezésre. Ilyennel már az előző fejezetben is dolgoztunk, hiszen a fájlok megragadása során a fogantyúk valójában ilyen adatfolyam objektumok voltak, csak ott nem használtuk ki ezen tulajdonságukat.

A következő példákban fájltömörítést és kibontást végzek. Az ehhez szükséges System.IO.Compression.GzipStream osztály ilyen adatfolyamon dolgozik, így itt kényszerűség is ennek használata. Nézzük tehát a tömörítést végző függvényt:

function Compress-GZip

{

    param

    (

        [String]$FilePath,

          [string] $OutFilePath

    )

 

    $inputstream = New-Object System.IO.FileStream $FilePath, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read)

 

    $buffer = New-Object byte[](1mb)

 

    $output = New-Object System.IO.FileStream $outFilePath, ([IO.FileMode]::Create), ([IO.FileAccess]::Write)

    $gzipStream = New-Object System.IO.Compression.GzipStream $output, ([IO.Compression.CompressionMode]::Compress)

    

    while(($byteCount = $inputstream.Read($buffer, 0, 1mb))){

         $gzipStream.Write($buffer, 0, $bytecount)

     }

    $inputstream.Close()

    $gzipStream.Close()

    $output.Close()

}

Ez a függvény a tömörítendő fájlra és az eredményfájlra mutató elérési utakat várja paraméterként. A függvényben három adatfolyam is van. Az $inputstream végzi a fájl beolvasását, az $output lesz a tömörített fájl és a $gzipStream pedig a kettő között tölti át a tömörített adatot. Az adatfolyamok olvasását végző Read, és írását végző Write metódusok hasonlóan működnek. Rendelkezésükre kell bocsátani egy bájttömböt, ami lehet kisebb, mint a teljes adatfolyam (itt most én - az egyszerűség kedvéért – 1MB-os puffert választottam). Ezek után egy while ciklusban, e puffer felhasználásával történik az adatfolyam kezelése. Kiolvasok mindig egy puffernyit a bemeneti adatfolyamból, illetve ha már a vége felé közeledek, akkor lehet, hogy kevesebbet. Ezt a Read visszatérési értékeként kapott tényleges beolvasott bájtok számát tartalmazó $byteCount változó adja meg. Ezt a puffert aztán átadom a gzip adatfolyamnak, ami a belsejében már a tömörített adatot adja át a fájlnak, ezzel már ott nekünk nem is kell foglalkozni. Amit az adatfolyamoknak akár Read, akár Write jelleggel átadunk puffert, azt ő magába olvasztja. A paramétereik között látható 0 érték tehát nem az ő adattartalmuk pozíciójára utal, hanem mindig a pufferéra, azt meg mindig az elejétől kell átadni, nem akarunk kihagyni soha akár egy bájtot se.

A kicsomagolást végző nagyon hasonló az előzőhöz, csak éppen a tömörítésből kicsomagolás lesz:

function Decompress-Gzip

{

    param

    (

        [String]$GZipFilePath,

        [String]$outFilePath

    )

 

    $inputstream = New-Object System.IO.FileStream $GZipFilePath, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read)

    $outputstream = New-Object System.IO.FileStream $outFilePath, ([IO.FileMode]::Create), ([IO.FileAccess]::Write)

    $buffer = New-Object byte[](1mb)

 

    $gzipStream = New-Object System.IO.Compression.GzipStream $inputstream, ([IO.Compression.CompressionMode]::DeCompress)

 

    while ($bytesRead = $GzipStream.Read($buffer, 0, 1mb)){

         $OutputStream.Write($buffer, 0, $bytesread)

    }

 

    $gzipStream.Close()

    $outputstream.close()

}

Az előző példákban én fájlokat használtam adattárolásra. A fájlok azért jók, mert megőrzik adattartalmukat hosszútávon is, és elég nagy tárolókapacitás áll általában rendelkezésünkre. Ha viszont nincs ezen előnyökre szükségünk, azaz ha csak átmenetileg akarunk adatokat tárolni és nem is olyan irtózatosan nagy mennyiségűt (a fizikai memóriához viszonyítva), akkor jól jöhet nekünk a memóriában tárolt adatfolyam is. Ez a System.IO.MemoryStream osztály. Szemben a tömbökkel, a memória-adatfolyamokat is ugyanúgy „szakaszosan” tudjuk írni és olvasni, azaz nem kell megadni előre a méretüket, dinamikusan bővülnek. Ugyan a tömbök bizonyos típusait is lehet újabb elemekkel bővíteni, de a memória-adatfolyamok kezelése sokkal hatékonyabb ebből a szempontból.

A memória-adatfolyam kezelése majdnem ugyanúgy történik, mint a fájloké, csak itt nem kell megadni elérési utat és nem kell a megosztással sem bajlódni. Vigyázzunk azonban a használatával, hogy ne nagyon haladjuk meg a benne tárolt adatmennyiséggel a rendelkezésre álló memória méretét, mert akkor a gépünk intenzív lapozó fájl használatba kezd, amivel végeredményben majdnem oda jutunk, mintha fájl-adatfolyamokat használnánk, de ráadásul a futó egyéb processzeink elől is elvesszük a memóriát, ami az ő teljesítményüket negatívan befolyásolja.



Word To HTML Converter