Search  
Saturday, June 24, 2017 ..:: Articole » Obiectul File System ::.. Register  Login
 Articole Minimize

Obiectul File System

Autor: Geoff Franklin
Notă: Windows File System oferă un mod orientat pe obiect pentru gestionarea fişierelor şi directoarelor. Este folosit pe scară largă în Visual Basic, dar în Visual FoxPro nu este răspândită folosirea sa. Motivul este, probabil, acela că Visual FoxPro are instrucţiuni native care sunt echivalente pentru cele mai multe din comenzi. În această expunere veţi găsi modul în care puteţi folosi această facilitate oferită de sistemul de operare pentru a îndeplini sarcini care, altfel, sunt mai dificil de dus la capăt.

Obiectul Windows File System (numit în continuare FSO) permite programatorului să gestioneze discurile, fişierele şi directoarele din Windows. El are o structură simplă: sistemul de fişiere este compus dintr-o colecţie de discuri, fiecare disc este o colecţie de directoare şi fiecare director este o colecţie de fişiere. În plus, există şi un obiect numit TextStream, care oferă un acces simplu la fişierele text.

fso1.gif

Eu am descoperit FSO în încercarea de a învăţa Visual Basic. Documentaţia sa din Visual Studio este însoţită de exemple scrise în Visual Basic, dar mie mi s-a părut la fel de folositor şi în Visual FoxPro.

Câteva exemple de cod

Multe din facilităţile oferite de FSO există deja în Visual FoxPro. De exemplu, codul FSO care listează fişierele dintr-un director arată astfel:

STORE CREATEOBJECT("Scripting.FileSystemObject") TO fso
STORE fso.GetFolder("C:\WINDOWS") TO fld
FOR EACH fil IN fld.Files
	? fil.Name
NEXT

Aceeaşi operaţiune poate fi executată (scriind mai puţin cod) în Visual FoxPro, astfel:

STORE ADIR(aFisiere,"C:\WINDOWS\*.*") TO nFisiere
FOR contoar = 1 TO nFisiere
	? aFisiere(contoar,1)
ENDFOR

Avantajul lui FSO este că poate să ofere mult mai mult decât numele, dimensiunea şi data modificării unui fişier. El poate întoarce calea de căutare, discul, atributele şi data creării, şi poate fi folosit pentru a modifica oricare din aceste informaţii. FSO are şi metode pentru a muta, copia, şterge şi crea fişiere şi directoare.

Unele din metodele lui FSO pot fi folosite pentru a înlocui apelurile API. De exemplu,

STORE fso.GetDrive("a") TO drv
IF drv.IsReady()
	? drv.SerialNumber
ELSE
	MESSAGEBOX("Introduceţi discheta în unitate",0,"Atenţie!")
ENDIF

Acest cod va verifica existenţa unei dischete valide în unitatea "A", şi dacă găseşte una, îi citeşte numărul de serie şi îl afişează în fereastra activă.

Folosirea FSO într-un formular

Formularul afişat în figura următoare crează un obiect FSO, scanează membrii colecţiei Discuri şi citeşte numele membrilor într-un masiv, care este folosit drept sursă a unui listbox. Când se face click pe un disc, se face referire la membrul corespunzător al colecţiei Discuri, şi textbox-urile din dreapta sunt actualizate corespunzător, conţinând date despre discul respectiv. Nu este prea folositoare ca aplicaţie de sine stătătoare, dar vă poate da idei pentru viitor şi demonstrează cu succes cum poate FSO să înlocuiască apelurile API.

fso2.gif

Toată treaba o fac metodele Load din formular şi InteractiveChange din listbox.

Metoda Load (detaliată în listingul următor) adaugă un obiect File System Object, apoi populează masivul folosit drept sursă pentru listbox. Singura chestiune de remarcat aici este aceea că am folosit o buclă FOR .. EACH pentru a parcurge colecţia de discuri. Ar fi fost frumos să mă pot referi la un disc ca la un membru din colecţie (de exemplu, fso.Drives[1]) dar această sintaxă nu este acceptată. În această situaţie, o abordare mult mai potrivită este cea cu FOR .. EACH.

Listingul 1. Metoda Load a formularului.

STORE CREATEOBJECT("Scripting.FileSystemObject") ;
	TO ThisForm.fso
* Câte discuri am?
STORE ThisForm.fso.Drives.Count TO m.lnNumDrives
* Crează un masiv suficient de mare pentru a
* stoca detaliile. Masivul este sursa pentru listbox.
DECLARE ThisForm.aDrives[lnNumDrives, 2]
STORE 1 TO ln
* Obţine detaliile pentru fiecare disc din
* colecţie şi le scrie în masiv
WITH ThisForm
	FOR EACH ldrv IN .fso.Drives
		STORE ldrv.DriveLetter TO .aDrives[ln,1]
		* Dacă încerc să accesez un disc inexistent
		* voi obţine un frumos mesaj de eroare.
		IF ldrv.IsReady = .T.
			STORE ldrv.VolumeName TO .aDrives[ln,2]
		ELSE
			STORE "Lipseşte discul" TO .aDrives[ln,2]
		ENDIF
		STORE ln + 1 TO ln
	NEXT ldrv
ENDWITH
* Aici încarc în al doilea masiv tipurile posibile pentru
* discurile din sistem.
Thisform.aTypes[1]="Floppy"
Thisform.aTypes[2]="Fix"
Thisform.aTypes[3]="Retea"
Thisform.aTypes[4]="CD-ROM"
Thisform.aTypes[5]="RAM disc"

Metoda InteractiveChange (apare în listingul 2) ilustrează restul. Aici este nevoie să extrag informaţiile despre discul selectat în listă. Metoda GetDrive îmi permite să transmit litera discului şi să obţin o referinţă către acel disc. Această metodă este remarcabil de flexibilă şi acceptă litere ca: "A", "C:" sau "D:\", cu majuscule sau cu minuscule. Dacă se transmite litera unui disc inexistent, ea întoarce o eroare OLE: "0x800a0044 Unknown COM status code". Este enervant, dar există un wrapper pentru ea: este vorba de eroarea FoxPro 1426. O puteţi intercepta pe asta şi să afişaţi un mesaj mai "uman".

Listingul 2. Metoda InteractiveChange

#DEFINE IC_MEGABYTE 1048576
* transformă cifra din bytes în Mb
* Obţine discul a cărei literă a fost selectată
WITH ThisForm
	STORE .fso.GetDrive(.lstDiscuri.Value) TO drvSelected
ENDWITH
WITH drvSelected
	STORE .DriveLetter TO ThisForm.txtLiteraDisc.Value
	* Se încearcă recunoaşterea tipului de disc
	IF .DriveType >= 1 AND .DriveType <= 5
		STORE ThisForm.aTypes[.DriveType] TO ;
		ThisForm.txtTipDisc.Value
	ELSE
		STORE "Necunoscut" TO ThisForm.txtTipDisc.Value
	ENDIF
	* Valorile următoare sunt disponibile numai dacă există disc.
	IF .IsReady = .T.
		STORE .VolumeName TO ThisForm.txtEtichetaDisc.Value
		STORE .SerialNumber TO ;
			THISFORM.txtNumarSerie.Value
		STORE .FileSystem TO ThisForm.txtSistemFisiere.Value
		STORE ROUND(.FreeSpace / IC_MEGABYTE,2) TO ;
			ThisForm.txtSpatiuLiber.Value
		STORE ROUND(.TotalSize / IC_MEGABYTE,2) TO ;
			ThisForm.txtSpatiuTotal.Value
	ELSE
		STORE "Lipseşte discul" TO ThisForm.txtEtichetaDisc.Value
		STORE "" TO ThisForm.txtNumarSerie.Value
		STORE "" TO ThisForm.txtSistemFisiere.Value
		STORE "" TO ThisForm.txtSpatiuLiber.Value
		STORE "" TO ThisForm.txtSpatiuTotal.Value
	ENDIF
ENDWITH
#UNDEFINE IC_MEGABYTE

Manipularea directoarelor şi a fişierelor

FSO posedă metode pentru crearea unui director sau fişier, şi metode pentru a muta fişiere sau directoare folosind măşti (caracterele * sau ?). Puteţi şterge un fişier apelând metoda Delete a lui FSO sau apelând metoda Delete a fişierului. Ambele metode de ştergere evită Recycle Bin şi şterg definitiv fişierul specificat.

Colecţiile Drives, Folders şi Files ale lui FSO sunt deosebite, şi trebuie să fie tratate diferit faţă de colecţiile din Visual FoxPro. Majoritatea colecţiilor obişnuite oferă două moduri de a accesa unul din membrii componenţi. De exemplu, puteţi să enumeraţi formularele active cu un set de instrucţiuni de genul FOR n = 1 TO _SCREEN.FormCount, sau de genul FOR EACH frm IN _SCREEN.FORMS. FSO nu permite scanarea colecţiilor sale cu un contoar într-o buclă FOR .. ENDFOR. Va trebui să folosţi FOR EACH. Această restricţie este deranjantă în timpul experimentelor cu aceste comenzi, dar odată căpătată experienţa, este folositoare. Nici nu vreau să-mi închipui problemele pe care le-ar putea pune o comandă de genul drv.Folders[7].Delete.

Puteţi folosi proprietatea Item a colecţiilor pentru a accesa un membru component, dar tot trebuie să ştiţi numele sau indexul respectivului membru. De exemplu, fso.Drives.Item("C") este membru a colecţiei Drives: un obiect Drive care indică discul C:. Această metodă acceptă parametri sub forma "c", "C:" şi "C:\".

Colecţia Folders mai are o diferenţă neaşteptată faţă de o colecţie obişnuită. Ea mai are un intermediar. În mod normal, obiectul Drive ar trebui să aibă o colecţie Folders, dar nu este aşa. Obiectul Drive nu are o colecţie Folders, ci o proprietate numită RootFolder. Acest RootFolder este un director ca toate celelalte şi are o colecţie SubFolders şi membrii acestei colecţii sunt toate directoarele de pe disc. După nedumerirea iniţială, ideea capătă sens: directoarele aflate discul D:, de exemplu, nu aparţin literei de disc ci sunt conţinute în directorul rădăcină "D:\".

Metoda din listingul 3 demonstrează cum se poate face o scanare recursivă a tuturor fişierelor din toate directoarele de pe disc. Metoda GetFiles inspectează toate fişierele dintr-un director, apoi se apelează recursiv pe sine însăşi pentru toate directoarele din colecţia SubFolders a directorului respectiv. Codul apelant scanează colecţia Drives şi transmite proprietatea RootFolder a fiecărui disc fix către metoda GetFiles. Rezultatul este că se vor inspecta toate directoarele pe harddiscurile calculatorului.

Listingul 3. Scanarea recursivă a directoarelor şi fişierelor.

* Face o căutare a fişierelor pe  discurile
* disponibile (locale).

FOR EACH drv IN fso.Drives
* Este un harddisc local?
	IF drv.DriveType = 2
		Thisform.GetFiles(drv.RootFolder)
	ENDIF
NEXT drv
    
* Methoda GetFiles
PARAMETER tfld
* Caută toate fişierele din director şi le adaugă
* într-un listbox dacă sunt de tipul "DBF."
FOR EACH fil IN tfld.Files
	IF UPPER(fso.GetExtensionName(fil.Name)) = "DBF"
		ThisForm.lstFiles.AddItem(fil.Path)
	ENDIF
NEXT fil

* Repetă operaţiunea pentru toate
* subdirectoarele din acest director.
FOR EACH fldSub IN tfld.SubFolders
	Thisform.Getfiles(fldSub)
NEXT fldSub

Căutarea directoarelor şi fişierelor "deosebite"

FSO are o metodă numită GetSpecialFolder care întoarce un obiect Folder cu trei valori posibile: directorul Windows, directorul System şi directorul Temp. Trebuie să îi transmiteţi un parametru pentru a obţine ce doriţi: GetSpecialFolder(0) întoarce directorul în care este instalat Windows-ul, GetSpecialFolder(1) întoarce directorul System şi GetSpecialFolder(2) întoarce directorul Temp. Aceste valori sunt constante predefinite în Windows Scripting, dar de sub Visual FoxPro nu sunt accesibile, şi în această situaţie metoda de apelare descrisă mai sus este singura posibilă.

Apelul metodei GetTempName va întoarce un nume de fişier temporar. Acest nume nu este garantat ca fiind unic. El are ca bază un număr hexazecimal aleator de cinci cifre (un exemplu tipic este "rad76F82.tmp"), aşa că există şansa (foarte redusă, ce-i drept) de a obţine duplicate. Dacă în viaţa reală şansele sunt destul de mici (la un număr realist de apeluri ale metodei), lucrurile se schimbă complet la teste dure. Pe un Pentium III/450 MHz, ATA66, 128 Mb RAM, într-un milion de apeluri, funcţia GetTempName a întors doar 642.649 de valori diferite, în timp ce SUBSTR(SYS(2015),3,10) a întors un milion de valori diferite. SYS(3) a întors doar 13 valori diferite, iar restul erau duplicate. Acesta este unul din cazurile în care metodele "bătrâneşti" sunt cu siguranţă mai bune.

Folosirea obiectului TextStream

FSO permite citirea şi scrierea fişierelor text cu ajutorul obiectului TextStream.

STORE ThisForm.fso.CreateTextFile("Config.fpw", 1) TO txsConfig
WITH txsConfig
	.WriteLine("DATE=BRITISH")
	.WriteLine("CURRENCY='Lei'")
	.Close
ENDWITH

Acelaşi fişier poate fi creat şi cu comenzile low-level FoxPro. Metodele Read şi Write ale obiectului FSO sunt echivalente cu comenzile FoxPro FREAD() şi FWRITE(), iar metodele WriteAll şi ReadAll sunt similare cu comenzile STRTOFILE() şi FILETOSTR().

Cum obţin şi cum instalez FSO?

FSO este oferit de o mare varietate de produse Microsoft. El se prezintă sub form unei biblioteci dinamice numită SCRRUN.DLL. Am găsit această bibliotecă pe toate calculatoarele pe care le-am văzut, cu o singură excepţie: un calculator care rula o versiune foarte veche de Windows95. Puteţi descărca versiunea cea mai nouă de la adresa http://msdn.microsoft.com/scripting şi nu pare să aibă probleme cu alte fişiere. Nu am avut nici un fel de probleme când am copiat-o într-un calculator mai vechi.

Cum aflu mai multe?

Windows File System nu este documentat în help-ul Visual FoxPro, dar există două capitole din Help-ul Visual Studio. Ele se numesc "FileSystemObject" şi "File System Object". Cele două capitole sunt similare, dar unul dintre ele este help-ul bibliotecii Scripting, iar celălalt deschide help-ul Visual Basic. Cea mai bună metodă de acces a documentaţiei este deschiderea directă a fişierului VBSCRIPT5.CHM.

Concluzie

Întrebare de 10 puncte: De ce să folosim FSO? Cu siguranţă, oferă o serie de funcţii, dar este dificil de folosit, gestionarea erorilor este cumplită şi este rău documentat. Multe din facilităţile oferite de FSO există deja, implementate în comenzi native Visual FoxPro. De exemplu, comanda FoxPro DRIVETYPE() este echivalentul lui fso.DriveType() sau FILE() este echivalentul lui fso.FileExists(). Facilităţile suplimentare ale lui FSO sunt folosite rar - eu personal nu-mi aduc aminte să fi vrut să ştiu numărul de serie al unei dischete. Pe de altă parte, ideea aia cu protecţia la copiere prin testarea numărului de serie a harddiscului, fără supărare, dar denotă lipsă de inteligenţă şi de bun simţ. În calitate de utilizator, eu unul i-aş da în cap unui programator care îmi vinde un program care încetează să funcţioneze dacă îl mut dintr-o partiţie în alta, formatez partiţia iniţială şi apoi îl aduc la loc, sau dacă îmi reinstalez sistemul de operare.

Pe de altă parte, FSO permite gestionarea OOP a directoarelor şi fişierelor din calculator, şi poate fi apelat din orice limbaj folosind aceeaşi sintaxă. Mai mult, sunt tentat să cred că FSO va deveni un standard care va înlocui comenzile moştenite de la DOS, dar există un articol pe sit-ul Microsoft care susţine că FSO nu poate întoarce dimensiunea corectă a discurilor de reţea mai mari de 2 Gb.

Pentru mine, această decizie este similară cu cea de a folosi comenzi xBase sau comenzi SQL pentru a manipula datele. Personal, mă simt mult mai confortabil folosind comenzile vechi şi bine ştiute APPEND şi REPLACE, şi am tendinţa să le folosesc atunci când manevrez datele "la mână", în fereastra de comenzi. Pe de altă parte, în codul pe care îl scriu folosesc INSERT INTO ... şi UPDATE, pentru că ştiu aceasta este calea pe care trebuie să o urmez.

Folosim sau nu FSO? Alegerea este a dumneavoastră.

Descărcaţi FSO DEMO.


    

 Google Ads Minimize

    

Copyright 2002-2013 Profox   Terms Of Use  Privacy Statement