Fájl-fogantyúk és tetszőleges méretű fájl létrehozása ([io.file])

A fájlok zárolása több szempontból is érdekes lehet számunkra. Egyrészt, ha pont nem szeretnénk, hogy egy fájl zárolva legyen, másrészt, ha éppen zárolni akarunk egy fájlt, hogy más ne férhessen hozzá.

A fájlok megnyitása a Windows mélyében egy összetett folyamat: fogantyú igénylése a fájlhoz, a jogosultságok ellenőrzése, fájl zárolása, fájl tartalmának olvasása vagy írása, fogantyú eleresztése. Ezt egyszerű felhasználóként szerencsére nem kell, hogy megtapasztaljuk, de néha jól jön, hogy ezeket a háttérfolyamatokat mi is vezérelhetjük. Ehhez a [System.IO.File ] osztály Open… jellegű statikus metódusait használhatjuk fel. Nézzük ezeket:

[1] PS C:\> [io.file] | gm -Static -Name open* | ft -Wrap

 

 

   TypeName: System.IO.File

 

Name      MemberType Definition

----      ---------- ----------

Open      Method     static System.IO.FileStream Open(string path, System.IO.F

                     ileMode mode), static System.IO.FileStream Open(string pa

                     th, System.IO.FileMode mode, System.IO.FileAccess access)

                     , static System.IO.FileStream Open(string path, System.IO

                     .FileMode mode, System.IO.FileAccess access, System.IO.Fi

                     leShare share)

OpenRead  Method     static System.IO.FileStream OpenRead(string path)

OpenText  Method     static System.IO.StreamReader OpenText(string path)

OpenWrite Method     static System.IO.FileStream OpenWrite(string path)

Az OpenRead olvasásra, az OpenWrite írásra, az OpenText szövegként való olvasásra próbálja megnyitni nyitva is tartani a fájlt. A „sima” Open meg teljes finomhangolást ad a kezünkbe a megnyitás módját illetően. Mindegyik megnyitási metódusban az a közös, hogy visszatérésükkor egy fogantyú objektumot adnak vissza, amin keresztül kapcsolatban maradunk a megnyitott fájlunkkal egészen addig, amíg be nem zárjuk azt. Fontos, hogy az így megkapott fogantyút ne felejtsük el betenni egy változóba, hiszen ha ezt nem tesszük meg, akkor nem tudjuk ezt újra megkaparintani, hiszen már egyszer zárolta számunkra a fájlt az operációs rendszer, így másodjára már el fogja utasítani, és csak a PowerShell alkalmazás bezárásával szabadul fel újra a fájl.

Nézzünk akkor ezek felhasználására példákat. Elsőként tegyük rá a kezünket egy fájlra olvasási jelleggel:

[2] PS C:\> $h = [io.file]::OpenRead("C:\ee\a.txt")

Ezután ez lett a $h változóban:

[3] PS C:\> $h

 

 

CanRead        : True

CanWrite       : False

CanSeek        : True

IsAsync        : False

Length         : 780

Name           : C:\ee\a.txt

Position       : 0

Handle         : 1888

SafeFileHandle : Microsoft.Win32.SafeHandles.SafeFileHandle

CanTimeout     : False

ReadTimeout    :

WriteTimeout   :

Látható, hogy a kérésünknek megfelelő fogantyút kaptunk vissza, azaz olvasni és keresni tudnánk a fájlban, de írni nem. Nézzük meg a $h tagjellemzőit is:

[4] PS C:\> $h | gm

 

 

   TypeName: System.IO.FileStream

 

Name                      MemberType Definition

----                      ---------- ----------

BeginRead                 Method     System.IAsyncResult BeginRead(byte[] a...

BeginWrite                Method     System.IAsyncResult BeginWrite(byte[] ...

Close                     Method     System.Void Close()

CreateObjRef              Method     System.Runtime.Remoting.ObjRef CreateO...

Dispose                   Method     System.Void Dispose()

EndRead                   Method     int EndRead(System.IAsyncResult asyncR...

EndWrite                  Method     System.Void EndWrite(System.IAsyncResu...

Equals                    Method     bool Equals(System.Object obj)

Flush                     Method     System.Void Flush()

GetAccessControl          Method     System.Security.AccessControl.FileSecu...

GetHashCode               Method     int GetHashCode()

GetLifetimeService        Method     System.Object GetLifetimeService()

GetType                   Method     type GetType()

InitializeLifetimeService Method     System.Object InitializeLifetimeService()

Lock                      Method     System.Void Lock(long position, long l...

Read                      Method     int Read(byte[] array, int offset, int...

ReadByte                  Method     int ReadByte()

Seek                      Method     long Seek(long offset, System.IO.SeekO...

SetAccessControl          Method     System.Void SetAccessControl(System.Se...

SetLength                 Method     System.Void SetLength(long value)

ToString                  Method     string ToString()

Unlock                    Method     System.Void Unlock(long position, long...

Write                     Method     System.Void Write(byte[] array, int of...

WriteByte                 Method     System.Void WriteByte(byte value)

CanRead                   Property   System.Boolean CanRead {get;}

CanSeek                   Property   System.Boolean CanSeek {get;}

CanTimeout                Property   System.Boolean CanTimeout {get;}

CanWrite                  Property   System.Boolean CanWrite {get;}

Handle                    Property   System.IntPtr Handle {get;}

IsAsync                   Property   System.Boolean IsAsync {get;}

Length                    Property   System.Int64 Length {get;}

Name                      Property   System.String Name {get;}

Position                  Property   System.Int64 Position {get;set;}

ReadTimeout               Property   System.Int32 ReadTimeout {get;set;}

SafeFileHandle            Property   Microsoft.Win32.SafeHandles.SafeFileHa...

WriteTimeout              Property   System.Int32 WriteTimeout {get;set;}

Látható, hogy a különböző elemi fájlkezelő műveletek metódusai mind ott sorakoznak. Van itt egy érdekes és egyben praktikus is, a SetLength. Ezzel be lehet állítani egy fájl méretét, azaz hogy mennyi területet foglaljon számára az operációs rendszer. Ez azért jó, mert így már jó előre le lehet foglalni a lemezterületet, és ha adatfolyamként írunk bele adatot (lásd következő fejezet), akkor sokkal gyorsabban fog ez menni, mivel nem kell folyamatosan újabb és újabb területeket megszerezni a fájlunk számára. Hogyan nézne ki akkor egy ilyen függvény, mellyel tetszőleges méretű fájlt lehet létrehozni:

function New-File {

param ($path, $size)

 

$h = [io.file]::Create($path)

$h.setlength($size)

$h.close()

}

Ha újra meg akarjuk ragadni ezt a fájlt olvasásra, akkor ez jelenleg sikerül, mivel az OpenRead az nem kizárólagosan zárolja a saját céljaira a fájlt:

[5] PS C:\> $h2 = [io.file]::OpenRead("C:\ee\a.txt")

[6] PS C:\> $h2

 

 

CanRead        : True

CanWrite       : False

CanSeek        : True

IsAsync        : False

Length         : 780

Name           : C:\ee\a.txt

Position       : 0

Handle         : 2300

SafeFileHandle : Microsoft.Win32.SafeHandles.SafeFileHandle

CanTimeout     : False

ReadTimeout    :

WriteTimeout   :

Ha már nincs szükségünk a fájlra, akkor engedjük el a fogantyút a Close metódussal:

[7] PS C:\> $h.close()

[8] PS C:\> $h2.close()

 Kizárólagosan is megnyithatjuk a fájlt, de ehhez az Open metódust kell használjuk, mert itt tudjuk a megosztási lehetőségeket meghatározni:

[21] PS C:\> $h = [io.file]::Open("C:\ee\a.txt","Open","Read","None")

Az Open metódusnál az első paraméter a fájl elérési útja. A második a megnyitás módja, azaz sima megnyitás legyen, létrehozás, felülírás, hozzáfűzés vagy ezek kombinációja. A pontos lehetőségek a System.IO.FileMode felsorolástípusból olvashatók ki. Miután én most egy meglevő fájlt akarok olvasni, ezért nekem elég az Open fájlmód. A harmadik paraméter az igényelt tevékenység, ami lehet Read, Write vagy ReadWrite. Nálam ez most Read. Végül azt állíthatjuk be, hogy másoknak mit engedek tenni ezzel a fájllal, amíg én is dolgozom rajta. Ez lehet semmi (None), olvasás, írás, olvasás-írás, törlés. Most én önző vagyok, másoknak semmilyen hozzáférést nem engedek.

Ha ezek után újból meg akarom nyitni ezt a fájl, akkor már hibát kapok:

[22] PS C:\> $h2 = [io.file]::OpenRead("C:\ee\a.txt")

Exception calling "OpenRead" with "1" argument(s): "The process cannot access

the file 'C:\ee\a.txt' because it is being used by another process."

At line:1 char:26

+ $h2 = [io.file]::OpenRead <<<< ("C:\ee\a.txt")

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : DotNetMethodException

Mire lehet mindezt felhasználni? Az elsődleges indok persze magának a fájlnak a megnyitása és zárolása, de ezzel a módszerrel lehet a pont azt is megvizsgálni, hogy egy fájl zárolva van-e már előlünk? Ha megpróbáljuk zárolni, de nem sikerül, akkor az azt jelenti, hogy valaki más már zárolta. Nézzünk erre egy függvényt, ami felderíti, hogy melyek a zárolt fájlok:

function Test-FileLock {

param(

    [Parameter(

        Mandatory = $true,

        ValueFromPipeline = $true,

        ValueFromPipelineByPropertyName = $true

    )]

    [Alias("FullName")]

    [string]

    $path   

)

process{

$file = Get-Item -Path $path -ErrorAction silentlycontinue -Force

if($file -and !$file.psiscontainer){

    $readlock = $true

    try{

        $h = [io.file]::Open($path,"Open","Read","None")

        $readlock = $false

    }

    catch{}

    if(!$readlock){

        $h.close()

    }

 

    $writelock = $true

    try{

        $h = [io.file]::Open($path,"Open","Write","None")

        $writelock = $false

    }

    catch{}

    if(!$writelock){

        $h.close()

    }

    Add-Member -InputObject $file -MemberType noteproperty -Name LockedForRead -Value $readlock

    Add-Member -InputObject $file -MemberType noteproperty -Name LockedForWrite -Value $writelock

    $file

}

}

}

Például ezzel a c:\ könyvtárra így lehet felderíteni a zárolt fájlokat:

[29] PS C:\> dir c:\ -Force | Test-FileLock | ft name, locked*

 

Name                                   LockedForRead            LockedForWrite

----                                   -------------            --------------

hiberfil.sys                                    True                      True

NemZárolt.txt                                  False                     False

pagefile.sys                                    True                      True

Megjegyzés

Természetesen ezzel a módszerrel nem csak akkor fogunk zárolási jelzést kapni egy fájlra, ha tényleg zárolva van, hanem akkor is, ha nincs megfelelő jogosultságunk a fájl olvasásához vagy írásához.



Word To HTML Converter