Failai ir katalogai

 

PERL programose darbui su failais naudojami taip vadinami deskriptoriai, sujungiantys PERL procesą su konkrečiu failu arba kitu procesu. Deskriptoriai iš esmės gali būti laikomi kintamaisiais, nors jų varduose nenaudojami PERL kintamiesiem būdingi prefiksai $ , @ , %. Deskriptoriai paprastai PERL programose rašomi didžiosiomis raidėmis, taip išskiriant juos programose. Praeitame skyriuje jau buvo kalbama apie standartinius deskriptorius STDIN STDOUT SRDERR, kurie atomatiškai sukuriami paleidžiant PERL programą (tai atlieka motininis procesas), tačiau panagrinėkime deskriptorius išsamiau.
 


Failų deskriptorius, failų atidarymas ir uždarymas

Deskriptorius - tai simbolinis vardas, naudojamas PERL programoje failo, įrenginio, lizdo (socket) ar programinio kanalo valdymui. Sukuriant deskriptorių, jis prijungiamas prie atitinkamo duomenų objekto ir naudojamas įvedimo/išvedimo operacijose. Deskriptorius sukuriamas atidarant failą funkcija open(). Jos sintaksė:

open(DESKRIPTORIUS,"failo_pavadinimas_ir_rėžimas");
   open(LOGFILE,">/temp/logfile.log");

Pavyzdyje sukuriamas deskriptorius LOGFILE ir susiejamas su failu /temp/logfile.log Failas atidaromas rašymo rėžimu (tai parodo simbolis ">"). Bet kurį failą galima atidaryti skaitymo, rašymo arba papildymo į failo galą rėžimu. Tai daroma prijungiant prefiksus prie failo pavadinimo:

     <   skaitymas;
     >   rašymas;
     >> papildymas

Jei prieš failo pavadinimą nenurodomas, joks prefiksas, tuomet pagal nutylėjimą jis atidaromas skaitymo rėžimu. Failą galima atidaryti ir skaitymo-rašymo režimu. Tam naudojamas simbolis + prieš aukščiau išvardintus prefiksus. Pavyzdžiui:  +<    +>   +>>. Kai naudojama +> , atidarant failą, jo turinys išvalomas, o esant rėžimui, aprašytam +>> išvedimas atliekamas į failo galą.
Kartais sukuriant failą, reikia apibrėžti tam tikras teises vartotojams, tuomet galima naudoti funkciją sysopen. Jos sintaksė:

sysopen(DESKRIPTORIUS, "failo_pavadinimas", rėžimas [,teisės]);
   sysopen(LOGFILE,"/temp/logfile.log", O_WRONLY | O_CREAT, 0600);

Čia failo_pavadinimas - tai failas be prefikso, o rėžimas - tai raktinis žodis, nurodantis rėžimą, kuriuo atidaromas failas; teisės - neprivalomas parametras, nustatantis failo teises. Žemiau pateiktas rėžimų reikšmių aprašymas.

O_RDONLY

Read only

O_WRONLY

Write only

O_RDWR

Read and write

O_CREAT

Create the file if it doesn't exist

O_EXCL

Fail if the file already exists

O_APPEND

Append to the file

O_TRUNC

Truncate the file

O_NONBLOCK

Non-blocking access

Sekanti lentelė parodo ryšį tarp funkcijų open ir sysopen naudojamų parametrų, apibrėžiančių failo atidarymo rėžimą.

Filename

Read

Write

Append

Create

Trunc

O_flags

Char

< file

yes

no

no

no

no

RDONLY

"r"

> file

no

yes

no

yes

yes

WRONLY TRUNC CREAT

"w"

>> file

no

yes

yes

yes

no

WRONLY APPEND CREAT

"a"

+< file

yes

yes

no

no

no

RDWR

"r+"

+> file

yes

yes

no

yes

yes

RDWR TRUNC CREAT

"w+"

+>> file

yes

yes

yes

yes

no

RDWR APPEND CREAT

"a+"


Funkcijos open ir sysopen grąžina reikšmes true arba false, priklausomai nuo to kaip pavyko atidaryti failą, todėl patartina pasitikrinti ar funkcija įvykdyta sėkmingai. Tam naudojamos funkcijos die() arba warn(), kurios išveda į STDERR pranešimus, apibrėžtus jų parametruose ir užbaigia PERL programą. Pavyzdžiui:

open (DATAPLACE,">/tmp/dataplace") || die "Negalima sukurti failo /tmp/dataplace\n";

open(LOG, ">>logfile") || die "Negalima papildyti: $! \n";    # Kintamasis $! išveda sisteminį klaidos pranešimą

sysopen(SOURCE, $path, O_RDONLY) or die "Negalima atidaryti $path : $!\n";

open(LOG,">>log") || warn "Discarding logfile output\n";

Baigus darbą su failu, jis uždaromas naudojant funkciją close(). Jos sintaksė:

close(DESKRIPTORIUS);

Uždarinėti failus patartina tuomet, kai programoje atidaromas ir nuskaitomas daugiau nei vienas failas. Nuskaitant failą, naudojamas specialus kintamasis $. kuriame saugomas paskutinio perskaityto įrašo numeris. Neuždarius failo, šio kintamojo reikšmė išlieka ir gali klaidinti atliekant nuskaitymą iš kito failo. Šiaip, baigus programą, failai uždaromi automatiškai.


Failų nuskaitymas ir kitos funkcijos

Informacijos nuskaitymas iš failo vykdomas operacijos <> pagalba, kurios operandas yra failo, atidaryto skaitymo rėžimu, deskiptorius. Naudojant šią operaciją skaliariniame kontekste, nuskaitoma po vieną eilutę (įrašą), o nuskaitytos eilutės numeris saugomas kintamajame $. Masyvo kontekste iš karto nuskaitomos visos failo eilutės. Eilučių (įrašų) atskirimo simbolis apibrėžiamas kintamajame $/ kuris pagal nutylėjimą yra "\n". Tačiau jį galima keisti.

open (EP,"/etc/passwd") || die "Klaida:$!\n";
while (<EP>) {
    chomp;
    print "Slaptazodziu faile yra $_ \n";     # Išvedama po vieną eilutę
}

open (IN,"in.dat") || die "Klaida:$!\n";
$line1 = <IN>;                                # Nuskaitoma pirma eilutė
$line
2 = <IN>;                                # Nuskaitoma antra eilutė
@rest = <IN>;                                 # Nuskaitomos likusios eilutės

open (EP,"/etc/passwd") || die "Klaida:$!\n";
print <EP>;                                   # Į STDOUT išvedamas visas failas
close EP or die "Klaida:$!\n";

Norint išvesti informaciją į atidarytą rašymui failą, naudojama funkcija print, kurios pirmasis parametras yra failo deskriptorius. Jei deskriptorius nenurodomas, išvedimas pagal nutylėjimą atliekamas į STDOUT.

print DESKRIPTORIUS, išvedama_info;
  print LOGFILE "Kintamojo \$max reikšmė $max\n";
  print STDOUT "Hello, world!\n";             # Tas pats kaip: print "hi, world!\n"

 

Kitos naudingos funkcijos

tell DESKRIPTORIUS;
Funkcija tell gražina esamą poziciją baitais faile, sujungtame su funkcijoje nurodytu deskriptoriumi. Jei deskriptorius praleistas, parodoma pozicija paskutiniame nuskaitytame faile.

seek DESKRIPTORIUS, perstūmimas, atskaitos_pozicija;
Funkcija seek pozicionuoja pointerį faile, nurodytame deskriptoriuje. Perstūmimas - tai skaičius baitų, per kuriuos reikia perkelti pointerį nuo atskaitos_pozicijos. Atskaitos pozicija gali turėti tris reikšmes: 0 - failo pradžia, 1 - esama pozicija, 2 - failo galas. Jei naudojamas modulis programoje IO::Seekable , vietoj skaičių galima naudoti tas pačias reikšmes turinčius raktinius žodžius: SEEK_SET,  SEEK_CUR,  SEEK_END. Pavyzdžiui:

use IO::Seekable;
seek FILE1, 5, 0;
seek FILE2, 5, SEEK_SET;

getc DESKRIPTORIUS;
Funkcija getc gražina simbolį iš esamos pointerio pozicijos faile, sujungtame su funkcijoje nurodytu deskriptoriumi. Jei deskriptorius praleistas, gražinamas simbolis iš STDIN.

read DESKRIPTORIUS, kintamasis, ilgis[, perstūmimas];
Funkcija read nuskaito iš failo, surišto su deskriptoriumi baitų skaičių, apibrėžtą parametre ilgis į kintamąjį . Perstūmimas nurodo kiek baitų bus prijungta prie kintamojo.

sysread DESKRIPTORIUS, kintamasis, ilgis[, perstūmimas];
syswrite
DESKRIPTORIUS, kintamasis, ilgis[, perstūmimas];

Tai nebuferizuoto nuskaitymo įrašymo funkcijos. Parametrų reikšmės analogiškos kaip ir funkcijos read atveju.


Failų tikrinimo operatoriai

Norint gauti informaciją apie failo atributus (teises, tipą, dydį) naudojama tokia PERL sintaksė:

-raidė DESKRIPTORIUS
-raidė išraiška

Išraiška sintaksėje suprantama kaip eilutė su failo pavadinimu ar skaliarinis kintamasis. Ši failo atributų tikrinimo operacija grąžina 1, jei failas turi tikrinamus atributus ir tuščią eilutę "" priešingu atveju. Jei parametre nurodytas failas neegzistuoja, gražinama reikšmė undef. Pavyzdžiai:

if (-e "index.html" && -e "index.cgi") {
    print "You have both styles of index files here.\n";
}
if (-x SOMEFILE) {
    print "File open on SOMEFILE is executable\n";
}

Žemiau pateiktoje lentelėje išvardintos visos galimos raidės ir jų reikšmės.

Raidė

Reikšmė

-r

File or directory is readable

-w

File or directory is writable

-x

File or directory is executable

-o

File or directory is owned by user

-R

File or directory is readable by real user, not effective user (differs from -r for setuid programs)

-W

File or directory is writable by real user, not effective user (differs from -w for setuid programs)

-X

File or directory is executable by real user, not effective user (differs from -x for setuid programs)

-O

File or directory is owned by real user, not effective user (differs from -o for setuid programs)

-e

File or directory exists

-z

File exists and has zero size (directories are never empty)

-s

File or directory exists and has nonzero size (the value is the size in bytes)

-f

Entry is a plain file

-d

Entry is a directory

-l

Entry is a symlink

-S

Entry is a socket

-p

Entry is a named pipe (a "fifo")

-b

Entry is a block-special file (like a mountable disk)

-c

Entry is a character-special file (like an I/O device)

-u

File or directory is setuid

-g

File or directory is setgid

-k

File or directory has the sticky bit set

-t

isatty() on the filehandle is true

-T

File is "text"

-B

File is "binary"

-M

Modification age in days

-A

Access age in days

-C

Inode-modification age in days

Failai UNIX operacinėje sistemoje yra siejami su indeksiniais deskriptoriais (inodes). Indeksinis deskriptorius - tai duomenų struktūra, kurią sudaro 13 laukų, kuriuose saugoma visa informacija apie failą.

Indeksinio deskriptoriaus struktūra

Lauko pavadinimas

Lauko reikšmė

dev

Įrenginio numeris failinėje sistemoje

ino

Indeksinio deskriptoriaus numeris

mode

Failo tipas ir teisės

nlink

Kietų ryšių (hard link) skaičius

uid

Failo savininko identifikacinis numeris

gid

Failo savininko grupės identifikacinis numeris

rdev

Įrenginio identifikatorius (specialių failų)

size

Failo dydis baitais

atime

Paskutinio kreipimosi į failą laikas (access time)

mtime

Modifikavimo laikas (modify time)

ctime

Indeksinio deskriptoriaus pakeitimo laikas

blksize

Bloko dydis

bloks

Faktiškas blokų skaičius, išskirtas failui

Norint gauti indeksinio deskriptoriaus laukų reikšmes naudojama funkcija stat. Jos sintaksė:

@var = stat DESKRIPTORIUS;
@var = stat išraiška;

($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat(...);
($uid, $gid) = (stat("/etc/passwd"))[4,5];

Funkcijos stat pagalba gaunama informacija ne tik apie failą, bet ir apie kietus ryšius (hard link) bei katalogus. Norint gauti informacija apie failo simbolinį ryšį, naudojama funkcija lstat. Sintaksė tokia pat kaip ir stat.


Operacijos su katalogais

UNIX operacinėje sistemoje katalogas laikomas specialaus formato failu, turinčiu tą pačią indeksinio deskriptoriaus struktūrą tik su kitokia rdev lauko reikšme. PERL darbui su katalogais naudojamos panašios funkcijos, kaip ir su failais t.y. nuskaitymo, įrašymo, uždarymo.

opendir DESKRIPTORIUS, katalogo_pavadinimas;
    opendir FF, "/usr/local";

Funkcijos opendir pagalba sukuriamas deskriptorius nurodytam parametruose katalogui.

readdir DESKRIPTORIUS;
    @dir = readdir FF;

Funkcija readdir nuskaito kataloge esančių failų pavadinimus ir priskiria juos masyvo elementams.

rewinddir DESKRIPTORIUS;
    rewinddir FF;

Funkcija rewinddir esamą poziciją perstato į pradžią ir leidžia iš naujo nuskaityti katalogą.

closedir DESKRIPTORIUS;
    closedir FF;

Funkcija closedir uždaro katalogą.

mkdir Katalogo_pavadinimas, teisės;
    mkdir "/home/test/solver", 0644;

Funkcija mkdir sukuria katalogą. Parametrų sąraše nurodomas failo pavadinimas ir teisės.

Pavyzdys

#! perl -w
opendir FDIR, "/usr/prog";
while ($name = readdir FDIR){
   next if -d $name;              # Jei katalogas
   print ("$name: dvejetainis\n") if -B $name;
}
closedir FDIR;

Į turinį