Perl-filoperasjoner. Bruke filbeskrivelser for å jobbe med filer i Perl

Perl gir et sett med unære operasjoner som returnerer verdien av bare ett felt i en inodestruktur. Disse operasjonene kalles "-X-operasjoner" i dokumentasjonen fordi navnene deres består av en bindestrek etterfulgt av et enkelt tegn. Alle av dem er unære navngitte operasjoner og har sin egen forrang i komplekse uttrykk.

Komplett liste over unære filkontrolloperasjoner

R Fil kan leses av effektiv uid/gid -w Skriv til fil av effektiv uid/gid -x Fil kan kjøres av effektiv uid/gid -o Filen eies av effektiv uid/gid -R Fil kan leses av effektiv uid /gid -W Skriv til fil kan være en gyldig uid/gid -X Fil kan kjøres av en gyldig uid/gid -O Filen eies av en gyldig uid/gid -e Filen finnes -z Filstørrelsen er null -s Fil størrelsen er ikke-null (returnerer størrelsen) -f Filen er normal (vanlig) fil -d Filen er en katalog -l Filen er en symbolsk lenke -p Filen er en navngitt programpipe (FIFO) eller håndtaket som sjekkes er assosiert med et programrør -S Fil er en socket -b Fil er en spesiell blokkfil -c Fil er en spesialtegnfil -t Filbeskrivelse bundet til terminal -u Fil setuid bitsett -g Fil setgid bitsett -k File stick bit sett y bit) -T Fil er en tekstfil -B Filen er binær (motsatt av tekst) -M Alder på filen i dager ved programkjøring -A Samme for fil siste tilgangstid -C Samme for fil inode siste endringstidspunkt

Unære operasjoner brukes på en streng som inneholder et filnavn, på et uttrykk hvis evaluering er et filnavn, eller på en Perl-filbeskrivelse. Hvis operasjonsparameteren ikke er spesifisert, tester den filen hvis navn er inneholdt i spesialvariabelen $_. Hver filattributtsjekkoperasjon returnerer 1 hvis filen har det tilsvarende attributtet, den tomme strengen "" ellers, og den udefinerte verdien undef hvis den angitte filen ikke eksisterer.

Noen få ord om algoritmen for å oppdage tekst og binære filer (operasjoner -T og -B). Disse operasjonene analyserer innholdet i den første blokken av filen for tilstedeværelsen av "rare" tegn - uvanlige escape-sekvenser eller bytes med høye biter satt. Hvis et tilstrekkelig stort antall slike tegn blir funnet (mer enn 30%), anses filen som binær, ellers tekst. Enhver fil med en tom første blokk anses som binær.

Når disse operasjonene brukes på Perl-filbeskrivelser, kontrolleres innholdet i I/O-bufferen, ikke den første blokken i filen. Begge disse operasjonene brukt på filbeskrivelser returnerer den boolske verdien True hvis filen knyttet til beskrivelsen er tom eller satt til slutten av filen.

Når du utfører unære navngitte filsjekkoperasjoner, kalles stat()-funksjonen faktisk implisitt, og resultatene av beregningen bufres, noe som lar deg bruke den spesielle filbeskrivelsen _ for å øke hastigheten på flere filkontroller:

If(-s("filnavn") && -T _) ( # Gjør noe for tekstfiler som ikke er null. . . . . . . . . . . . . . .)

chdir

Endre gjeldende arbeidskatalog til katalogen spesifisert av verdien til EXPRESSION-parameteren. Hvis parameteren utelates, blir hjemmekatalogen gjeldende katalog. Returnerer sann hvis erstatningsoperasjonen for gjeldende katalog lyktes, ellers False.

Chdir [EXPRESSION]

chmod

chmod LISTE

chmod()-funksjonen endrer tillatelsene til filene i listen gitt til den som en parameter. Det første elementet i denne listen må være et tresifret oktalt tall som spesifiserer tilgangsrettighetene for eieren, brukerne i eierens gruppe og andre brukere. Hvert oktale siffer definerer retten til å lese filen, skrive til filen og kjøre den (hvis filen representerer et kjørbart program) for brukergruppene ovenfor. De angitte bitene av dens binære representasjon gjenspeiler de riktige filtillatelsene. For eksempel, hvis alle tre bitene er satt (oktalt nummer 7), så har den tilsvarende brukergruppen alle de oppførte rettighetene: de kan lese fra en fil, skrive til en fil og utføre den. En verdi på 6 bestemmer rettigheten til å lese og skrive, 5 lar deg lese fra en fil, kjøre den, men lar deg ikke skrive til denne filen osv. Vanligvis opprettes en ikke-kjørbar fil med tilgangsmodus 0666 - alle brukere kan lese og skrive informasjon til filen, en kjørbar fil - med modus 0777. Hvis fileieren ønsker å begrense skriving til filen til brukere som ikke tilhører gruppen hans , så skal følgende setning utføres:

Chmod 0664, "file.dat";

Returverdien til chmod()-funksjonen, som chown()-funksjonen, er antallet filer fra listen som endringstillatelsesoperasjonen ble fullført.

På DOS- og Windows-operativsystemer er det bare innstillingen for eiertilgangsmoduser som betyr noe.

chown

chown LISTE

Enhver bruker som lager sin egen fil anses som eieren. Du kan endre eieren av en fil fra et Perl-skript ved å bruke chown()-funksjonen. Argumentet til denne funksjonen er en liste hvis to første elementer må representere de numeriske identifikatorene uid og gid. De gjenværende elementene i listen er navnene på filene som eieren blir endret for. Denne funksjonen returnerer antall filer som endringen eier og gruppeoperasjonen var vellykket for.

Eksempel:

@list = (234, 3, "fil1.dat", "fil2.dat"); $nummer = chown(@liste); advar "Ikke alle filer har endret eierskap!" hvis $nummer != @liste-2;

Bare eieren eller superbrukeren (vanligvis systemadministratoren) av et UNIX-system kan endre eieren av en fil. På operativsystemer med et filsystem som ikke er UNIX (DOS, Windows), fungerer denne funksjonen, men innstillingene påvirker ikke tilgangen til filen.

chroot

Definerer en ny rotkatalog for alle relative (begynner med en skråstrek "/") filnavn for brukerens prosess og dens underordnede prosesser. Endrer ikke gjeldende arbeidskatalog. I fravær av en parameter, brukes verdien til spesialvariabelen $_. Kan bare kalles opp av superbrukeren.

Chroot DIR_NAME

Lukk

lukk DESCRIPTOR

Når arbeidet med filen er fullført, lukkes den av funksjonen close(). Den eneste valgfrie parameteren til denne funksjonen er håndtaket knyttet til filen.

Denne funksjonen returnerer True hvis I/O-bufferen ble tømt og systemfilhåndtaket ble lukket. Kalt uten en parameter, lukker funksjonen filen knyttet til gjeldende håndtak satt av select()-funksjonen.

Når filavslutningsfeil oppstår, kan de oppdages ved å bruke spesialvariabelen $!: close (FILE) eller die "Feil ved lukking av fil: $!";

lukket

Lukker katalogen knyttet til kataloghåndtaket spesifisert av parameteren DECRIPTOR. Returnerer en boolsk verdi True hvis katalogen ble lukket.

Closedir HÅNDTAK

fcntl

Implementerer fcntl(2) Unix-systemkommandoen. Før bruk må du få tilgang til definisjonene av systemkonstanter med use Fcntl-setningen.

Returverdi: hvis systemfunksjonen returnerer -1, er Perl-funksjonen udefinert; hvis systemfunksjonen returnerer 0, returnerer Perl-funksjonen strengen "0 men sant"; hvis systemfunksjonen returnerer en annen verdi, returnerer Perl-funksjonen den samme verdien.

Fcntl HÅNDTAK, FUNKSJON, SKALAR

glob

Returnerer filene funnet i gjeldende katalog hvis navn samsvarer med det gitte mønsteret (ved bruk av Unix-metategnene "*","?"). Verdien til uttrykket må være en streng som inneholder et mønster av filnavn.

Glob EXPRESSION

ioctls

Implementerer Unix ioctl(2) systemkommandoen. Før bruk må du få tilgang til definisjonene av systemkonstanter med require "ioctl.ph"-setningen;

Returverdi:

  • hvis systemfunksjonen returnerer -1, er Perl-funksjonen udefinert;
  • hvis systemfunksjonen returnerer 0, returnerer Perl-funksjonen strengen "0 men sant";
  • hvis systemfunksjonen returnerer en annen verdi, returnerer Perl-funksjonen den samme verdien.
fcntl HÅNDTAK, FUNKSJON, SKALAR

link

Link GAMMEL, NY

lstat

Returnerer en liste over feltverdier for inodestrukturen til en symbolsk lenke til en fil. Hvis parameteren utelates, brukes verdien til spesialvariabelen $_.

lstat [DECRIPTOR] lstat [EXPRESSION]

Brukes for å få informasjon om symbolske lenker. Returnerer en liste over feltverdier for inodestrukturen til selve lenken, ikke filen den refererer til. Denne funksjonen fungerer på samme måte som stat()-funksjonen.

mkdir

Oppretter en ny katalog med navnet spesifisert av DIRECTORY-parameteren og tilgangsmodusen spesifisert av MODE-parameteren. Returnerer en boolsk True ved vellykket katalogopprettelse, False ellers, og inn i $! en feilmelding legges inn.

Mkdir-KATALOG, MODUS

åpen

åpne DECRIPTOR, FILE_NAME; åpen HÅNDTAK;

Et håndtak er nødvendig for å få tilgang til en fil fra et Perl-program. Open()-funksjonen brukes til å lage et håndtak. Når en åpen operasjon utføres med et filnavn spesifisert i parameterne, åpnes den tilsvarende filen og det opprettes et håndtak til denne filen. Et uttrykk kan brukes som en filbeskrivelse - verdien vil være navnet på beskrivelsen. Filnavnet er gitt direkte som en streng bokstavelig eller som et uttrykk hvis verdi er en streng. En åpen operasjon uten filnavn åpner filen hvis navn er inneholdt i skalarvariabelen $DECRIPTOR, som ikke kan være en leksikalsk variabel definert av my()-funksjonen.

Eksempel:

#! perl -w $var = "out.dat"; $FILE4 = "fil4.dat"; åpne FIL1, "in.dat"; # Filnavnet er gitt av strengen åpen FILE2, $var; # Filnavn gitt av åpen FILE3, "/perlourbook/01/".$var; # Filnavnet evalueres i den åpne FILE4-setningen; # Filnavn i variabelen $FILE4

Hvis et ikke-kvalifisert filnavn er gitt, åpnes filen med det angitte navnet og som ligger i samme katalog som Perl-programmet. Du kan spesifisere hele filnavnet, men husk at det avhenger av operativsystemet du bruker. For eksempel, på Windows, må du spesifisere stasjonsnavnet: d:/perlbook/file1.doc

Enhver fil kan åpnes i en av følgende moduser: les, skriv eller legg til på slutten av filen. Dette gjøres ved å legge til riktig prefiks til filnavnet:

  • < (чтение)
  • > (rekord)
  • >> (legg ved)

Hvis prefikset er utelatt, åpnes filen som standard i lesemodus.

Å skrive informasjon til en fil åpnet i skrivemodus utføres i begynnelsen av filen, noe som fører til ødeleggelse av informasjonen i den før den åpnes.

Informasjonen i en fil som er åpnet i tilleggsmodus, blir ikke ødelagt, nye poster legges til på slutten av filen.

Hvis en fil med det angitte navnet ikke eksisterer når en fil åpnes i skrive- eller tilføy-modus, opprettes den, noe som skiller disse filåpne-modusene fra lesemodus, der filen må eksistere. Ellers mislykkes den åpne operasjonen og det tilsvarende håndtaket opprettes ikke.

Perl lar deg åpne en fil i enda en annen modus - lese/skrivemodus.

For å gjøre dette, før leseprefikset<, записи >eller legge til >> bør sette et +-tegn.

  • +< - сохраняют содержимое открываемого файла
  • +> - sletter først innholdet i den åpnede filen
  • +>> - lagre innholdet i den åpnede filen, skriving til filen utføres alltid på slutten av filinnholdet

åpnedir

Åpner katalogen hvis navn er lik verdien til EXPRESSION-parameteren og knytter den til håndtaket spesifisert av DECRIPTOR-parameteren. Katalogbeskrivelsesnavn lagres i det opprinnelige navnerommet til Perls navnetabell.

Opendir HÅNDTAK, UTTRYKK

lesekobling

Returnerer verdien av den symbolske lenken spesifisert av EXPRESSION hvis symbolske lenker er implementert av operativsystemet; ellers en fatal feil. Hvis systemfeil ble mottatt mens du henter verdien av den symbolske lenken, returnerer en udefinert verdi og inn i spesialvariabelen $! en feilmelding legges inn. Hvis parameteren utelates, brukes verdien til $_-variabelen.

lesekobling [EXPRESSION]

endre navn

Gi nytt navn til en fil. Returnerer 1 hvis endringen var vellykket, ellers 0.

Gi nytt navn til OLD_NAME, NEW_NAME

stat

I UNIX-filstrukturen lagres informasjon om en fil i inoden. Inodestrukturen består av 13 felt, for hvilke spesielle notasjoner brukes:

Felt Beskrivelse
devEnhetsnummer i filsystemet
inoInodenummer
modusFilmodus (type og tillatelser)
nlinkAntall harde lenker til filen (i mangel av lenker er det lik 1)
idFileier numerisk ID
guideNumerisk gruppe-ID for eieren av filen
rdevEnhets-ID (kun for spesielle filer)
størrelseFilstørrelse i byte
tidTiden filen sist ble åpnet siden epoken
mtimeFil sist endret tid siden epoke
ctimeInodemodifikasjonstid siden epoke
blksstørrelseForetrukket blokkstørrelse for I/O-operasjoner
blokkerDet faktiske antallet tildelte blokker for å imøtekomme filen

Ikke alle de oppførte inodestrukturfeltene støttes av alle filsystemer.

Stat()-funksjonen er designet for å få verdiene til feltene til filen inode-struktur. Den eneste parameteren kan enten være et filnavn eller et håndtak til en fil som er åpnet i programmet. Den returnerer en liste med 13 elementer som inneholder feltverdiene til filens inodestruktur i den rekkefølgen de er oppført i tabellen.

En typisk bruk i et Perl-program vises nedenfor:

($dev,$ino,$modus,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blokker) = stat($filnavn);

Å tilordne feltverdier til en liste over skalarvariabler med identifikatorer som tilsvarer feltnavn gjør programmet mer lesbart enn å tilordne til en rekke skalarer:

@inode = stat($filnavn);

I sistnevnte tilfelle kan verdien av det tilsvarende feltet bare oppnås ved å bruke en indeks, noe som ikke er veldig praktisk, siden du må huske nummeret på det nødvendige strukturfeltet.

Hvis ingen parameter er spesifisert når stat()-funksjonen kalles, returnerer den inodestrukturen til filen hvis navn er inneholdt i spesialvariabelen $_.

Få filinformasjonsfunksjonen returnerer en liste over filinodestrukturfeltverdier ved suksess i en listekontekst, eller en tom liste ved feil. I skalarsammenheng returnerer den en boolsk verdi på True eller False avhengig av resultatene av dens utførelse.

For enkel bruk av informasjon om filen, bufrer stat()-funksjonen de mottatte feltverdiene ved suksess. Hvis denne funksjonen kalles opp med den spesielle filbeskrivelsen _ (understrek), vil den returnere informasjonen som er lagret i hurtigbufferen fra forrige samtale. Dette lar deg sjekke ulike attributter til en fil uten å kalle opp stat()-funksjonen igjen eller lagre resultatene av dens kjøring i programvariabler.

Stat()-funksjonen kan brukes til å få inodestrukturen til ikke bare en fil, men også harde lenker til den, så vel som kataloger, siden de også er filer hvis datablokker inneholder navnene på katalogens filer og deres numeriske inoder .

symbolkobling

Symbolkobling OLD_NAME, NEW_NAME

umask

Setter prosessens tilgangsmodusmaske gitt av EXPRESSION (oktal) og returnerer den forrige verdien av tilgangsmodusmasken.

Umask UTTRYKK

koble fra

Slett filer spesifisert av LIST. Returnerer antall vellykket slettede filer.

Fjern tilknytningen til LIST

tid

utime LISTE

Det er tre felt i strukturen til filen inode, som lagrer tidspunktet for siste tilgang til filen (atime), dens modifikasjon (mtime) av filen og modifikasjonen av inoden (ctime). Utime()-funksjonen kan brukes til å endre tidspunktet da en fil sist ble åpnet og endret. Parameteren er en liste som inneholder navnene på filene som behandles, og de to første elementene i listen er de numeriske verdiene for de nye siste tilgangs- og endringstidene:

@filer = ("fil1.dat", "fil2.dat"); $nå = tid; utime $now, $now, @filer;

I denne kodebiten endres siste tilgangs- og endringstidspunkt for filer fra @files-listen til gjeldende tidspunkt oppnådd ved bruk av tidsfunksjonen.

Merk at når funksjonen utime() utføres, endres også tidspunktet for siste modifikasjon av inoden (ctime) - den settes lik gjeldende tid. Returverdien er antallet filer som den siste aksess- og endringsoperasjonen for endring var vellykket.

Hver gang en fil på disken må åpnes, må et nytt håndtak opprettes og åpnes. For å åpne håndtak, bruk åpne-funksjonen:
åpen (filbeskrivelse, bane)
Banen spesifiserer hvilken fil som skal åpnes, så hvis den fullstendige banen ikke er spesifisert, for eksempel c:/windows/system/, vil åpne-funksjonen forsøke å åpne filen i gjeldende katalog. Ved suksess returnerer den åpne funksjonen en verdi som ikke er null (True), ved feil returnerer den undef (False), for eksempel:
if (open(MINFIL, "mindatafil")) (
#Kjør etter vellykket åpning
) annet (
print "Feil ved åpning av filen mindatafil\n";
exit1;
}

I mange Perl-programmer kan en lignende "åpne eller rapporter feil"-syntaks implementeres med funksjonen . Die-funksjonen stopper kjøringen av programmet og skriver ut en feilmelding:
Døde på script_name line xxx
Her er skriptnavnet navnet på Perl-programmet, xxx er linjenummeret der dysefunksjonen ble oppdaget. Die og åpne funksjoner brukes ofte sammen slik:
åpen(MINTEKST, "roman.txt") || dø;
Programmet åpner enten filen eller avslutter kjøringen. Hvis åpningen mislykkes, og returnerer falsk, kommer den logiske ELLER-operatoren (| |) inn. Som et resultat vil argumentet som ligger på høyre side av operatøren (i dette tilfellet formfunksjonen) bli evaluert. Hvis den åpne funksjonen er vellykket utført, blir ikke høyre side av det logiske uttrykket evaluert. Noen ganger bruker de en annen form for logisk ELLER - eller.

For å lukke håndtaket, bruk funksjonen Lukk :
lukk(MINTEKST);
Hvis du prøver å åpne en fil, og spesifiserer en av de allerede åpnede beskrivelsene som parametere for den åpne funksjonen, lukkes denne beskrivelsen først og åpnes deretter på nytt.

Funksjoner en liste med argumenter kan sendes, som vises i stedet for standardmeldingen. Hvis meldingen ikke inneholder et linjeskifttegn, blir teksten på script_name line xxx lagt til på slutten, for eksempel:
die "Feil ved åpning av fil";
# Viser meldingen "Feil ved åpning av fil på skriptnavnlinje xxx"
die "Feil ved åpning av fil\n" ; # Viser "Feil ved åpning av fil"

Perl gir en spesiell variabel $! A som inneholder feilmeldingen som oppsto under siste systemoperasjon (for eksempel en disk I/O-operasjon). I en numerisk sammenheng er $! returnerer et lite talende feilnummer. I strengsammenheng er $! returnerer en operativsystemfeilmelding:
åpen(MINFIL, "minfil") || die "Feil ved åpning av filen min: $!\n";
Hvis denne funksjonen ikke klarer å åpne filen fordi den ikke eksisterer, vil en melding vises:
Feil ved åpning av minfil: en fil eller katalog i banen eksisterer ikke.

Ikke bruk $-variabelen! for å sjekke suksessen til systemfunksjonen. Verdien av denne variabelen bestemmes umiddelbart etter at en systemoperasjon (for eksempel I/O) er utført, og bare når den operasjonen har mislyktes. I alle andre tilfeller vil $! kan ha en helt vilkårlig meningsløs betydning.

Noen ganger må du vise en advarsel i programmet og fortsette kjøringen. For å generere advarsler, bruk funksjonen varsle , lik die, bortsett fra at programkjøringen fortsetter:
if (! åpen(MINFIL("utdata")) (
advarsel "Feil ved åpning av filutgang: $!";
) annet (
# Leser fildata...
}

Perl har flere måter å lese filer definert av filbeskrivelser på. Det vanligste er å bruke filinndataoperatoren, også kalt vinkeloperatoren <> . For å lese informasjon fra en fil, plasser dens beskrivelse i vinkelparentes og tilordne denne verdien til en variabel, for eksempel:
åpen(MINFIL, "minfil") || die "Feil ved åpning av filen min: $!";
$line= ; #Leser en fil

En vinkeloperator i skalarkontekst leser én linje fra en fil. Hvis filen slutter, returnerer vinkeloperatoren undef. En linje i en tekstfil er en sekvens av tegn avgrenset av en spesiell linjeavslutning. I UNIX er denne funksjonen et linjematingstegn (ASCII-kode 10), i DOS og Windows er det en sekvens av vognretur- og linjematingstegn (ASCII-koder: 13 og 10). Standard linjeavslutningspekeren kan endres i Perl, noe som gir noen interessante effekter.

Du kan bruke følgende kode for å lese og skrive ut innholdet i en hel fil (eksemplet forutsetter at MYFILE er et åpent filhåndtak):
while (definert($a= )) {
skriv ut $a;
}

For å lese informasjon fra en fil er det praktisk å bruke en while-løkke. Hvis du bruker en vinkeloperator i stedet for en betinget i en while-løkke, tildeler Perl automatisk den angitte strengen til spesialvariabelen $_ og løkker til filen slutter:
samtidig som( ) {
skriv ut $_;
}

I dette tilfellet er while-setningen ansvarlig for å tilordne den angitte strengen til $_-variabelen og se etter tegnet på at slutten av filen er nådd. Denne interessante oppførselen skjer bare i en while-løkke, og bare når det betingede uttrykket består av en vinkeloperator. Ikke glem at dataene som leses fra filen, i tillegg til selve teksten, også inneholder linjeslutttegn. Hvis du bare vil ha tekst, bruk chomp-funksjonen for å bli kvitt tegnene på slutten av linjen.

I sammenheng med en liste, leser vinkeloperatøren hele filen og tilordner den til listen. Hver linje i filen er tilordnet det tilsvarende elementet i listen eller matrisen, som vist nedenfor:
åpen(MINFIL, "novel.txt") || dø "$!";
@innhold= ;
lukk(MINFIL);

Dette eksemplet leser alle dataene fra novel.txt gjennom MYFILE-beskrivelsen og tilordner den til @contents-matrisen. Dette tilordner den første linjen i novel.txt-filen til det første elementet i @contents-matrisen: $contents . Den andre linjen er tilordnet $contents og så videre.

For å skrive data til en fil, må du først åpne selve filen for skriving. Syntaksen for å åpne en fil for skriving er nesten den samme som for lesing:
åpen(håndtak, ">bane")
åpen(Beskriver, ">>bane")

Syntaksen til den første linjen er allerede kjent for oss, med unntak av symbolet > foran stien. Denne karakteren forteller Perl at nye data skal skrives til filen hvis sti følger. I dette tilfellet slettes allerede eksisterende data i filen og den angitte beskrivelsen åpnes for skriving. I det andre eksemplet, symbolene >> forteller Perl at filen åpnes for skriving, men hvis filen allerede eksisterer, legges de nye dataene til etter de eksisterende dataene. Her er noen eksempler:
# Nye data overskriver gamle data, hvis noen
open(NEWFH, ">output.txt") || die "Feil ved åpning av output.txt: $!";
# Nye data legges til eksisterende.
open(APPFH, ">>logfile.txt") || die "Feil ved åpning av logfile.txt: $!";

Etter at du er ferdig med å jobbe med en fil som er åpen for skriving, blir det av største betydning å lukke filen og frigjøre håndtaket. Lukkfunksjonen forteller operativsystemet at skrivingen til filen er fullført, og at dataene skal plasseres på den permanente lagringsplassen på disken, for eksempel:
lukk(NEWFH);
lukk(APPFH);

Når en fil er åpen for skriving, er det veldig enkelt å legge inn data i den. Dette gjøres ved hjelp av den velkjente funksjonen skrive ut . Så langt har printfunksjonen kun blitt brukt av oss til å vise data på skjermen. I prinsippet kan denne funksjonen brukes til å skrive data til en hvilken som helst fil. Syntaksen til utskriftssetningen for å sende ut data til en fil er veldig enkel:
skriv ut beskrivelsesLISTE

open(LOGF, ">>loggfil") || dø "$!";
if (! Skriv ut LOGF "Logged ", scalar(localtime), "\n") (
advarsel "Feil ved skriving til loggfil: $!";
}
lukk(LOGF);

Du kan ha flere filer åpne samtidig for lesing eller skriving, som vist i følgende eksempel:
åpen(KILDE, "kildefil") || dø "$!";
open(DEST, ">destinasjon") || dø "$!";
@innhold= ; # "Spis" kildefilen
skriv ut DEST $innhold; # Skriv den til en annen fil
close(DEST);
lukk(KILDE);

Dette eksemplet utfører en enkel filkopiering. Forresten, du kan forkorte koden noe ved å kombinere lese- og skriveoperasjoner i en setning:
skriv ut DEST ;
Siden utskriftsfunksjonen forventer at en liste sendes som en parameter, vil setningen er i listesammenheng. Vinkelsetningen i listekontekst leser hele filen, og utskriftssetningen sender den til DEST-beskrivelsen.

Når du skriver binære data som GIF-filer, EXE-filer, MS Word-dokumenter, etc., er datakonvertering ikke nødvendig. Derfor, for å forhindre at verken Perl eller operativsystemet utfører slike konverteringer, før du skriver binære data til en fil, må du bruke funksjonen bin-modus . Den markerer filbeskrivelsen som en dobbel
personlig. Binmode-funksjonen kalles etter at filen er åpnet, men før inndata eller utdata er gjort:
open(FH, "camel.gif") || dø "$!";
binmode(FH); # Håndtaket blir binært.

Når en fil er åpnet, kan binmode-funksjonen bare brukes på håndtaket én gang. Å lukke og åpne den binære filen vil kreve at binmode-funksjonen kalles opp igjen. Å bruke binmode på systemer som ikke skiller mellom tekst og binære filer (som UNIX) gjør ingenting.

Før du åpner en fil, er det en god idé å forsikre deg om at den virkelig eksisterer, for å se om det er en katalog, og det vil ikke resultere i en feilmelding om tillatelse nektet. Perl har spesiell fil testerklæringer . De har alle lignende syntaks:
-X filbeskrivelse
-X-bane

Her er X den spesifikke testoperasjonen og file_descriptor er håndtaket som testes. Filen kan testes uten å åpne beskrivelsen.

Vanlig brukte filtestutsagn
-r
-r "fil"
Sant hvis "fil" er tillatt å lese
-w
-w $a
Sant hvis filen som er navngitt i $a er skrivbar.
-e
-e "fil"
Sann verdi hvis "fil" eksisterer
-z
-z "fil"
Sant hvis "fil" eksisterer, men er tom
-s
-s "fil"
Returnerer størrelsen på "fil" i byte, hvis den finnes
-f
-f "fil"
Sant hvis "fil" er en vanlig fil (ikke en katalog)
-d
-d "katalog"
Sant hvis "katalog" spesifiserer en katalog
-T
-T "fil"
Sant hvis 'fil'-parameteren spesifiserer en tekstfil
-B
-B "fil"
Sant hvis parameteren 'fil' spesifiserer en binær fil
-M
-M "fil"
Returnerer antall dager som har gått siden "filen" sist ble endret

print "Hvor skal vi lagre dataene?";
$filnavn= ;
chomp $filnavn;
if (-s $filnavn) (
advarsel "Innholdet i $filen vil gå tapt!\n";
advare "Det har blitt endret",
-M $filnavn, "dager siden.\n";
}

Mange Perl-programmerere jobber med tekstfiler som konfigurasjoner eller loggfiler, så det er viktig å lære å jobbe med filer så tidlig som mulig for å få nyttig kunnskap.

La oss først lære hvordan du skriver data til en fil, da dette ser ut til å være den enkleste oppgaven.

Før du skriver til en fil, trenger du åpen det, det vil si, be operativsystemet (Windows, Linux, OSX, etc.) om å åpne en kanal der programmet ditt kan "snakke" til filen. Perl har en funksjon for dette

åpen

(med litt merkelig syntaks). bruk streng; bruk advarsler; min $filnavn = "rapport.txt"; open(min $fh, ">", $filnavn) eller dø "Kan ikke åpne "$filnavn" $!"; print $fh "Min første rapport generert med perl\n"; lukk $fh; skriv ut "ferdig\n";

Dette er et godt fungerende eksempel, og vi kommer tilbake til det senere, men la oss først prøve et enklere eksempel:

Enkelt eksempel

bruk streng; bruk advarsler; open(min $fh, ">", "report.txt"); print $fh "Min første rapport generert med perl\n"; lukk $fh; skriv ut "ferdig\n";

Også her trengs det en forklaring. Funksjon åpen tar 3 parametere.

Den første, $fh , er en skalarvariabel som vi erklærer i open()-kallet. Vi kunne ha deklarert det tidligere, men det er vanligvis lettere å deklarere det direkte i samtalen, selv om dette kan se litt rart ut ved første øyekast. Den andre parameteren bestemmer hvordan vi åpner filen. I dette tilfellet setter vi et større enn-tegn (> ), som betyr at filen åpnes for skriving. Den tredje parameteren er banen til filen vi ønsker å åpne.

Når denne funksjonen kalles, tilordner den en spesiell nøkkel til $fh-variabelen kalt et filhåndtak. Vi bryr oss ikke om innholdet i denne variabelen; senere bruker vi det bare. Viktigst, merk at innholdet i filen fortsatt er på disken, og IKKE kommer inn i $fh-variabelen.

Når filen er åpen, kan vi bruke $fh-pekeren i print()-setningen. Dette ser nesten ut som print() i andre deler av opplæringen vår, men vi sender filpekeren som den første parameteren, og etter den Nei(!) komma.

Dette print()-kallet vil skrive tekst til filen vår.

Så i neste linje lukker vi filpekeren. Dette er strengt tatt ikke påkrevd i Perl. Perl vil automatisk og grasiøst lukke alle filpekere når variabelen går utenfor scope, det vil si i verste fall når skriptet avsluttes. Men uansett, eksplisitt lukking av filer anses som god praksis.

Den siste utskriftslinjen "ferdig\n" er bare nødvendig for å klargjøre følgende eksempel:

Feil under behandling

La oss ta det forrige eksemplet og erstatte filnavnet med en bane som ikke eksisterer. For eksempel:

Åpne(min $fh, ">", "noen_merkelig_navn/rapport.txt");

Nå, hvis vi kjører dette skriptet, vil vi se en feilmelding:

Print() på lukket filhåndtak $fh ved ... ferdig

Egentlig er dette bare en advarsel; skriptet fortsetter å kjøre, og derfor vil vi se ordet "ferdig" på skjermen.

Dessuten vil vi bare se advarselen fordi vi eksplisitt ba om at advarsler skal vises sammen med bruksadvarslene. La oss prøve å kommentere bruksadvarsler og se at nå er skriptet stille når det ikke klarer å åpne filen. Så du vil ikke engang merke det før klienten, eller enda verre, sjefen din, begynner å klage.

I alle fall er det et problem. Vi prøvde å åpne filen. Det gikk ikke, men vi prøvde likevel å skrive noe der.

Vi bør sjekke om open() lyktes før vi fortsetter.

Heldigvis returnerer selve open()-kallet TRUE ved suksess og FALSE ved fiasko, så vi kan gjøre dette:

Åpne eller dø (åpne eller dø)

åpne (min $fh, ">", "noen_merkelig_navn/rapport.txt") eller dø;

Dette er "standard idiom" åpne eller dø. Veldig vanlig i Perl.

die er et funksjonskall som vil gi et unntak og dermed avslutte skriptet vårt.

«åpne eller dø» er et boolsk uttrykk. Som du vet fra forrige del av opplæringen, er "eller" i Perl (som på mange andre språk) forkortet. Dette betyr at hvis venstre side returnerer TRUE, er det umiddelbart klart at hele uttrykket vil være TRUE, så høyre side blir ikke utført i det hele tatt. På den annen side, hvis venstre side returnerer FALSE, vil høyre side bli utført, og resultatet av utførelsen vil være resultatet av hele uttrykket.

I dette tilfellet bruker vi denne stenografifunksjonen i uttrykket vårt.

Hvis open() lykkes, vil den returnere TRUE og høyresiden vil aldri bli utført. Skriptet vil ganske enkelt hoppe til neste linje.

Hvis open() mislykkes, vil den returnere FALSE. Da utføres også uttrykket til høyre for eller. Dette gir et unntak og skriptet avsluttes.

I dette eksemplet sjekker vi ikke den endelige verdien til det logiske uttrykket, vi trenger det ikke. Vi brukte dette uttrykket bare for "bivirkningens skyld".

Hvis vi kjører skriptet med denne endringen, får vi en feilmelding:

Døde kl...

og vil IKKE se "ferdig".

Forbedrer feilmeldingen

I stedet for bare å kalle die uten en parameter, kan du legge til en forklaring på hva som skjedde.

Åpne(min $fh, ">", "noe_rart_navn/report.txt") eller dø "Kan ikke åpne filen "noe_rart_navn/rapport.txt"";

Kan ikke åpne filen "some_weird_name/report.txt" ...

Dette er bedre, men på et tidspunkt vil noen prøve å endre banen til riktig katalog...

Åpne(min $fh, ">", "correct_misspelled_dir/report.txt") eller dø "Kan ikke åpne filen "some_strange_name/report.txt"";

Men feilmeldingen vil være gammel fordi banen ble endret bare i open()-kallet, ikke i meldingen.

Så det er bedre å bruke en variabel som filnavn:

Mitt $filnavn = "noen_merkelig_navn/rapport.txt"; open(my $fh, ">", $filename) or die "Kan ikke åpne filen "$filename"";

Nå har vi den riktige feilmeldingen, men vi vet fortsatt ikke hvorfor det skjedde. La oss gå ett skritt videre og bruke $! - Perls innebygde variabel - for å gi oss hva systemet fortalte oss om feilen:

Mitt $filnavn = "correct_dir_with_typo/report.txt"; open(min $fh, ">", $filnavn) eller die "Kan ikke åpne filen "$filnavn" $!";

Denne koden vil gi

Kan ikke åpne filen "correct_misprinted_directory/report.txt" Ingen slik fil eller katalog ...

Så mye bedre.

Vel, nå tilbake til det opprinnelige eksemplet.

Mer?

Større enn-tegnet i den åpne samtalen kan virke forvirrende, men hvis du er kjent med kommandolinjeomdirigeringer, vil du forstå hva det betyr. Og hvis ikke, se for deg at det er en pil som viser retningen på dataflyten: til filen til høyre.

Ikke latin?

Hvis du trenger å jobbe med ikke-ASCII-tegn, bør du lagre dem i UTF-8. For å gjøre dette, må du fortelle Perl at du åpner en UTF-8-kodet fil.

Åpne(min $fh, ">:encoding(UTF-8)", $filnavn) eller "Kan ikke åpne filen "$filnavn"";

De to viktigste operasjonene angående innholdet i filene er input(les) fra en fil og konklusjon (skriv) til en fil.

For å jobbe med innholdet i en fil må programmet åpen. Ved å åpne en fil spesifiserer vi nøyaktig hva vi vil gjøre med den: lese eller skrive. Resultatet av funnet er den såkalte filbeskrivelse - en skalarverdi som lagrer informasjon om gjeldende status for lese- eller skriveprosessen. Lese, skrive og andre input/output operasjoner utføres videre gjennom beskrivelsen.

En fil åpnes ved å bruke den innebygde åpne prosedyren. Prosedyren tar tre parametere: en variabel for håndtaket som skal opprettes, en streng som indikerer åpen modus (lese, skrive eller noe annet), og til slutt filnavnet:

Perl

min $fil ; åpne $file , "<" , "MyFile.txt" ; åpning for lesing

Vi elsker å kombinere deklarering av en variabel for et håndtak med et kall til den åpne prosedyren:

Perl

åpen min$file , "<" , "MyFile.txt" ;

Betydning"<" , переданное как второй параметр, символизирует чтение. Знак «меньше», повернувшийся спиной к имени файла, как бы намекает нам, что готовится извлечение информации fra fil. Gjett hvordan du åpner en fil for skriving? Selvfølgelig slik:

Perl

åpne min $fil , ">" , "Min fil.txt" ; åpning for skriving

I eksemplene på bruk av den åpne prosedyren ble det relative navnet på filen angitt - i forhold til katalogen som er gjeldende katalog for dette programmet. Umiddelbart etter å ha startet programmet, er dette katalogen programmet ble lansert fra. Men gjeldende katalog kan endres med chdir:

Perl

chdir "/" ;

Det er ingen kontraindikasjon for å spesifisere et absolutt filnavn ved åpning:

Perl

åpne min $passwd , "<" , "/etc/passwd" ;

På noen operativsystemer bruker fullstendige filnavn en annen katalogseparator. For eksempel, under Microsoft DOS og Microsoft Windows, brukes omvendt skråstrek-separator \ i stedet for skråstreken / . Men når du spesifiserer det fullstendige navnet i et Perl-program ved åpning, bør en skråstrek brukes: "/c:/dos/autoexec.bat" .

Intuisjon forteller oss at alt som åpner må lukkes før eller siden. Dette gjelder også for filer. Ethvert I/O-skript er strukturert på samme måte: åpning, faktisk input eller output, og til slutt, lukking

Å lukke en fil frigjør operativsystemressursene som ble brukt da den ble åpnet og sikrer at dataene som er skrevet til filen når den tiltenkte destinasjonen. Etter lukking mister deskriptorvariabelen sin relevans og kan ikke brukes for I/O.

Den innebygde lukkeprosedyren brukes til å lukke filer:

Perl

lukk $fil ;

Du bør ikke forvente at det alltid vil være vellykket å åpne en fil. Det er mange grunner som kan komme i veien. Blant dem:

  • den manglende filen;
  • ingen lese- eller skrivetillatelser;
  • medieproblemer: ødelagt disk eller flash-stasjon, nettverksbrudd i tilfelle nettverksfiler.

I disse og lignende tilfeller vil alle videre operasjoner på filen miste all mening og vil bare irritere Perl. Imidlertid rapporterer den åpne prosedyren i sin returverdi resultatet av operasjonen: den returnerer sant ved suksess, og usant ved feil. Et velskrevet program bør se etter denne verdien, og handle ut fra den. For eksempel, hvis åpningen mislykkes, avslutter du programmet med den aktuelle meldingen:

Perl

hvis (åpen ) { jobbe med en fil og deretter lukke ) annet ( dø ; )

Vær oppmerksom på den spesielle variabelen $! . Hvis det oppstår en feil, blir tekst automatisk plassert i denne variabelen som forklarer årsaken til feilen, for eksempel Ingen slik fil eller katalog eller Ingen tilgang eller noe annet. Tekst i $! , avhengig av systeminnstillingene, kan være på et annet språk.

Følgende formspråk ser mye mer elegant ut:

Perl

åpen eller dø "Kan ikke åpne filen: $!\n";

Dette boolske uttrykket har to operander. Hvis den første (det åpne returnerer) evalueres til sann, er det ikke nødvendig å evaluere den andre, siden hele uttrykket allerede er sant. Hvis open returnerer false, bestemmes verdien av hele uttrykket av den andre operanden, som i dette tilfellet må evalueres. For beregningen vil formprosedyren bli kalt med alle de påfølgende konsekvenser.

Programmet er selvfølgelig ikke pålagt å avslutte hvis filen ikke åpnes. For eksempel, hvis du skal behandle flere filer, kan du ganske enkelt gå videre til neste ved å rapportere feilen ved å bruke advarselsprosedyren:

Perl

for (@filnavn ) ( åpne $filen min , "<" , $_ or warn "Kan ikke åpne filen $_:$!" og neste ; arbeid med neste fil og dens påfølgende lukking }

Det er to måter å lese fra en beskrivelse: byte/tegn og linje for linje.

Når du leser en fil byte-for-tegn, ber programmet om neste del av data av den nødvendige størrelsen fra den åpne deskriptoren og gir en skalarvariabel for de forespurte dataene. For lesing, bruk den innebygde prosedyren les:

Perl

les $fil , $buffer , 16 ;

Du kan tenke på en fil som er åpnet for lesing, som en sekvens av byte. En tenkt peker skiller den allerede leste delen av sekvensen fra den uleste delen. Leseoperasjonen resulterer blant annet i å flytte pekeren til slutten av filen. På grunn av dette vil neste lesekommando ha tilgang til et nytt stykke data. Filbeskrivelsen lagrer en rekke informasjon om den åpne filen, inkludert denne pekeren - nummeret til den første uleste byten. Rett etter åpning er pekeren null.

Hva skjer hvis du ber om flere byte når du leser enn størrelsen på den uleste delen av filen? Det er greit, datamaskinen går ikke i stykker. Det er bare det at færre byte enn det ble forespurt vil bli sendt til buffervariabelen. Det er praktisk å kontrollere dette fenomenet ved å bruke returverdien til leseprosedyren - dette er antallet byte som kan leses. Et vanlig formspråk i Perl-programmering er:

Perl

while (les $file , $buffer , $size ) ( gjøre noe med $buffer }

Her brukes verdien returnert fra read som løkkebetingelsen. Før eller siden vil filen bli lest til slutten, og neste leseanrop vil returnere null (false). Dette vil bryte syklusen, som er akkurat det vi trenger.

I motsetning til byte/tegnlesing, når et spesifisert antall byte eller tegn er forespurt, med linje-for-linje lesing, er ikke størrelsen på lesingen spesifisert på forhånd. I stedet lyder det linje- en sekvens av byte eller tegn opp til tegnet eller tegnene som markerer slutten av strengen.

Linje for linje avlesning utføres av operatøren<…>. Koden<$file >fører til at neste linje fra $filbeskrivelsen leses inn i standardvariabelen $_ .

Det er praktisk å bruke en while-løkke for å behandle alle linjer i en fil sekvensielt. For eksempel kan et program som skriver ut innholdet i en fil til skjermen, linje for linje, se slik ut:

Perl

åpne $filen min, "<" , "file.txt" or die "Kan ikke åpne filen: $!\n"; samtidig som (<$file >) ( skrive ut ; )

Her stiller leseren med rette spørsmålet: hva er det egentlig som trykker utskriftsprosedyren i løkken? Standardvariabelen, selvfølgelig. Det ville vært mulig å skrive print $_ , men dette vil neppe gi klarhet.

Et annet eksempel. Den allerede åpnede filen inneholder tall, ett per linje. Det er nødvendig å vise summen deres på skjermen.

Perl

min $sum =0 ; samtidig som (<$file >) ( chomp ; $sum +=$_ ; ) skriv ut "$sum\n" ;

Chomp-kommandoen er nødvendig av denne grunn. Operatør<…>sammen med strengen, leser den også tegnet som avslutter strengen, noe som vil skape et problem hvis lesestrengen deretter deltar i et aritmetisk uttrykk. Den innebygde prosedyrechompen fjerner dette tegnet hvis strengen slutter med det. Hvis det siste tegnet er annerledes, gjør prosedyren ingenting. denne forholdsregelen er nødvendig i tilfelle, dessverre, filen ikke ender med et linjeskifttegn. Da vil den siste linjen som leses fra filen ende med noe annet. Det er også en chop-prosedyre som fjerner og returnerer det siste tegnet i en streng, uansett hva det er. Både chop og chomp opererer på en streng som sendes som en parameter, men i fravær av en parameter, på $_-variabelen.

Vi bør ikke tro at vi med linjelesingsoperatoren er dømt til å bruke $_-variabelen. Hvis du vil lese inn i en annen variabel, bruk en oppgave:

Perl

$s =<$file >;

Det er på tide å rapportere om en funksjon ved linjelesingsoperatøren. Betydningen endres litt hvis operatøren plasseres i en listekontekst, det vil si der listen skal være. For eksempel, hvis du tilordner til en matrise:

Perl

@s=<$file >;

I dette tilfellet vil alle linjer som leses fra filen fylle matrisen. Du kan også organisere en iterativ loop:

Perl

skrive ut for<$file >;

Denne koden, som while-løkken ovenfor, skriver ut linjene i en fil til skjermen. Koden vil gi samme resultat.

Perl

skrive ut<$file >;

(ordet for mangler her). Men vi anbefaler ikke denne tilnærmingen fordi den først leser alle linjene fra filen og deretter sender dem som en liste over parametere til utskriftsprosedyren. I dette tilfellet opptar alle linjer unødvendig minne, og med en stor fil kan minnemengden være veldig stor.

Generelt kan linje-for-linje-lesing skape et lignende problem hvis det er veldig lange linjer i filen. Og selv om dette ikke er typisk for tekstfiler (for eksempel opprettet i et tekstredigeringsprogram), bør denne omstendigheten tas i betraktning.

Å åpne en fil for lesing forutsetter at filen eksisterer, ellers resulterer åpning i en feil. Hvis filen åpnes for skriving, er det ikke lenger nødvendig å kreve filens eksistens: den manglende filen opprettes tom. Hvis filen eksisterte, blir alt innholdet ødelagt, og vi får igjen en tom fil.

For å skrive til deskriptoren brukes utskriftsprosedyren, som lenge har vært kjent for oss, men ikke helt slik vi er vant til:

Perl

skriv ut $fil $string ;

Her er innholdet i $strengen skrevet til den åpne $filbeskrivelsen. Vær spesielt oppmerksom på fraværet av komma etter den første $file-parameteren. Med et komma vil betydningen av kommandoen være annerledes: ingenting vil bli skrevet til beskrivelsen, men i stedet vil programmet vise strengrepresentasjonen av verdiene til både $file og $stringvariablene:

GLOB(0x989e830) Hei!

(det heksadesimale tallet i parentes vil mest sannsynlig være annerledes, og det kan være annen tekst i stedet for ordet Hei!). Dette tallet forteller oss ingenting, akkurat som det mystiske ordet GLOB sammen med parenteser. Så hvis alle parametere for utskriftsprosedyren er atskilt med kommaer, skrives de alle ut på skjermen. Hvis det ikke er komma etter den første parameteren, må den parameteren være et skrivbart håndtak, og resten av parameterne skrives til den:

Perl

skriv ut $file "Hei," , $bruker ;

Du kan legge ved alle parametere etter beskrivelsen i parentes:

Perl

skriv ut $fil ("Hei," , $bruker);

En fremtredende Perl-språkekspert anbefaler å omslutte beskrivelsen i krøllete klammeparenteser for å visuelt skille den fra resten av parameterne:

Perl

print ($file) "Hei," , $bruker;

Programmerere kommer ofte over en situasjon der det er nødvendig å plassere skiftende fragmenter i malteksten på bestemte steder. Perl egner seg godt til slike oppgaver. Det er veldig praktisk å plassere de skiftende delene av teksten i en variabel, og sette inn variabelnavnet på riktig sted i en streng omsluttet av doble anførselstegn:

Perl

skrive ut "Kjære $name! Du skylder $toll rubler. Betal innen $date, ellers $straff.\n";

På denne måten kan du sette inn både strenger og tall i malen. Når det gjelder tall, kan det i noen situasjoner være nødvendig med spesiell formatering. Tall før de tas med i malen må kanskje avrundes til ønsket antall desimaler etter punktet, polstret til venstre med nødvendig antall nuller eller mellomrom slik at tallet ser bra ut i tabellen. Du må kanskje sette inn et tall i binært eller heksadesimalt format.

I slike situasjoner kommer de innebygde prosedyrene printf og sprintf til unnsetning. Den første parameteren i begge prosedyrene er den såkalte formatstreng. Dette er en maltekst der andre parametere skal settes inn fra bestemte steder. Steder for innsetting av parametere og ønsket format er merket på en spesiell måte. Etiketten er et prosenttegn etterfulgt av en formatbetegnelse. Resten av prosedyreparametrene settes inn i stedet for formatmerkene i riktig format. Printf-prosedyren skriver ut resultatet til en deskriptor som utskriftsprosedyren, mens sprintf returnerer strengen oppnådd etter alle innsettinger for annen bruk. I prinsippet, hvis det ikke fantes printf , kunne det enkelt programmeres: å kalle printf (...) tilsvarer print (sprintf (...)) .

Nå mer om formatstrenger og formatmerker.

Heksadesimalt format med null utfylling til tre sifre:

Bruken av prosenttegnet som markør fratar oss muligheten til å bruke det i formatstrengen som sådan. Denne vanskeligheten er ikke ny for oss, og den løses på en velkjent måte. En kombinasjon av to prosenttegn betyr et enkelt prosenttegn (ligner på hvordan \\ innenfor "" -strenger betyr ett skråstrek):

Perl

$p =38 ; $x =43 ; printf "%d%% av %d er lik %d\n", $p , $x , $p /100 *$x ;

38 % av 43 tilsvarer 16

Akkurat som print , kan printf-prosedyren skrive ut ikke bare til skjermen, men også en filbeskrivelse som er åpnet for skriving eller vedlegg:

Perl

printf($fil) ;

Perl har to sett med funksjoner for å utføre lese-/skriveoperasjoner på en fil. Funksjonene til ett sett bruker en buffer - et visst minneområde - for å samle informasjon som er lest / skrevet til en fil, etter å ha fylt den eller lukket filen, blir bufferdataene fysisk skrevet til disk eller sendt til programmet. Disse funksjonene, som inkluderer print , readline,<>, read , getc , seek , og tell er i hovedsak grensesnittfunksjoner til Cs standardbufrede I/O-bibliotekrutiner. Ved å bruke bufret I/O går det raskere å lese/skrive data til filer. Funksjonene til det andre settet, som inkluderer sysread, syswrite og sysseek, refererer direkte til I/O-funksjonene til operativsystemet, og utfører direkte fysiske datalese-/skriveoperasjoner uten å samle dem i en mellombuffer. Du kan åpne en fil for tilgang med både bufret og ikke-bufret funksjoner med en av de to funksjonene - åpen () eller sysopen () - når du åpner en fil, er det ikke regulert hvilket sett med funksjoner som skal behandle informasjonen i den . Det eneste kravet er at det ikke anbefales å blande disse to tilnærmingene for samme fil i samme åpne økt, da dette kan føre til uforutsigbare resultater.

OBS Når du arbeider med den samme filen, må du ikke blande bufret og ubufret I/O-funksjonskall. Denne praksisen kan føre til uforutsigbare kollisjoner. Hvis du for eksempel ønsker å bruke ubuffrede lese-/skrivefunksjoner, og informasjonen fra filen allerede er lest av den bufrede o-operasjonen, bør du lukke filen, åpne den igjen og bruke ubuffrede funksjoner for å jobbe med den.

Bufret I/O

Oftest behandler programmet tekstfiler. Operasjon<>, hvis operand er en filbeskrivelse, leser informasjon fra filen i hele "records", som vanligvis representerer linjer i en tekstfil. Brukt i en skalar kontekst, leser den gjeldende filpost, og øker spesialvariabelen $. som holder styr på antall leste poster. I listesammenheng vil den samme operasjonen lese alle filens poster hvis det er den første som utføres på den filen, eller de resterende postene hvis det har vært andre lesninger fra filen før den, og returnere en liste hvis elementer er filens opptegnelser lest. Mer presist, operasjonen<>i listekontekst, leser de gjenværende postene til filen, med utgangspunkt i dens nåværende posisjon, som implisitt endres med hver leseoperasjon, og kan endres eksplisitt ved å bruke søke()-funksjonen, som vi vil bli kjent med litt senere. Ser vi fremover, la oss si at alle filer i Perl ikke har noen struktur, men er representert, som i C, som en strøm av byte. Postseparatoren er lagret i spesialvariabelen $/, og som standard er det nylinjetegnet \n. Således, hvis brukeren ikke satte sin egen postseparator, så under filposten i operasjonen<>betyr en linje i en tekstfil. Å sette en annen postseparator gjøres ved den vanlige operasjonen å tilordne et nytt tegn eller sekvens av postseparatortegn til $/-variabelen. Listing 6.9 viser noen triks for å lese fra en fil med operasjonen<>. Oppføring 6.9. Lesing fra en fil ved operasjon<>#! perl -w åpen (F1, "in.dat") eller dø "Feil ved åpning av fil: $!"; open(F2, "out.dat") eller dø "Feil ved åpning av fil: $!"; $line1 = ; # Første oppføring av filen in.dat $line2 = ; # Andre filoppføring in.dat @rest = ; # Gjenværende registreringer av filen in.flat $/ = ">"; # Sett en annen postseparator @f2 = ; # Skriv ut leseposter for filen out.dat for($i=0; $i<=$#f2; $i++) { print "Запись ".($i+1).": $f2[$i]\n"; } $/ = "\n"; # Восстановление разделителя по умолчании close (Fl) or die $!; close(F2) or die $!; open(F3, "out.dat") or die "Ошибка открытия файла: $!"; print ; # Skriv ut hele filen close(F3) or die $!; Noen kommentarer til programmet i liste 6.9. Den første og andre linjen i in.dat-filen leses inn i henholdsvis $line1 og $line2 variablene, siden standard postseparator \n brukes. Elementene i @rest-matrisen lagrer linjer fra den tredje til den siste av den samme filen, siden leseoperasjonen i tilordningssetningen utført i listekontekst. Før du leser postene til out.dat-filen, settes en ny postseparator - symbolet >. Hvis out.dat-filen, for eksempel, bare inneholder én linje Ivanov> Petrov> Sidorov> End, vil elementene i @f2-matrisen inneholde følgende verdier: $f2 = "Ivanov>" $f2[l] = " Petrov>" $f2 = " Sidorov>" $f2 = "Slutt"
MERK Hvis, når out.dat-filen er opprettet, dens enkeltlinje avsluttes av en ny linje (Enter-tasten trykket), vil $f2 inneholde strengen "End\n".
I den siste utskriftserklæringen til oppføring 6.9, operasjonen utføres i en listekontekst fordi print()-funksjonen er en listeoperasjon og krever en liste med verdier. Hvis vi imidlertid ønsker å forordne hver post med noe tekst ved utskrift, antar vi å bruke følgende setning for dette: skriv ut "Record:". ; da ville vi få en utskrift av kun den første linjen i filen, siden i dette tilfellet operasjonen vil bli utført i den skalarkonteksten som er opprettet av operasjonen for strengsammenkobling (.). For å få ønsket resultat bør du bruke en while-løkke: while( ) ( skriv ut "Entry: ".$_; # Skriv ut neste linje i den tilknyttede # filbeskrivelsen F3 ) Husk at hvis resultatet av operasjonen<>ikke er tilordnet noen variabel, så lagres resultatet av dens utførelse i spesialvariabelen S_. Faktisk, driften av å lese poster<>i Perl er den implementert av den innebygde readline() funksjonen, som også kan kalles direkte. Dens eneste parameter er en referanse til en fildeskriptor, og siden beskrivelsen ikke tilhører noen av de gyldige datatypene (scalar, array of scalars, eller hash array), bør du bruke en referanse til Perls spesielle interne datatype typeglob. For å gjøre dette, prefiks filbeskrivelsen med *: readline *DESCRIPTOR; For eksempel er følgende to utsagn fullstendig likeverdige: $line = ; $line = leselinje *STDIN; Naturligvis gjelder alt som ble sagt om postseparatorene lagret i spesialvariabelen $/ også for readline() operasjonen. Skriving til en fil som er åpnet i skrive- eller tilføy-modus gjøres av print()-funksjonen, med den første parameteren som en filbeskrivelse: print DECRIPTOR OUTLIST; Denne operasjonen skriver innholdet i listeelementene i den rekkefølgen de er definert i funksjonskallet, og legger ikke til noen postseparator eller linjeskifttegn på slutten av listen. Programmereren må ta seg av dette selv, enten ved å eksplisitt legge til en postseparator eller et linjeskifttegn på slutten av utdatalisten, eller ved å bruke muligheten gitt av spesialvariabelen $\. Utskriftsfunksjonen legger til innholdet i denne spesielle variabelen til slutten av utdatalisten, som som standard inneholder den tomme strengen: # Eksplisitt postseparator print F1 @recl1, "\n"; $\ = "\n"; # Sette postseparatoren # Nå skrives postseparatoren ut implisitt # av hver følgende funksjon print print F1 @recl2;
ADVARSEL Det må ikke være komma mellom filbeskrivelsen og det første elementet i utdatalisten. Hvis dette skjer, vil perl-tolkeren gi en feilmelding: Ingen komma tillatt etter filhåndtering.
Når du skriver informasjon til en fil med print()-funksjonen, kan du dra nytte av en annen nyttig funksjon. Hvis verdien til spesialvariabelen $ er satt, settes den inn mellom elementene i utdatalisten. For eksempel, hvis vi vil at verdiene til listeelementene ikke skal vises som en kontinuerlig strøm av tegn, men atskilt med et mellomrom, bør vi sette verdien til denne spesialvariabelen til et mellomrom: $var1 = "11111 "; Svar2="22222"; skriv ut $var1, $var2, "\n"; $, = " "; skriv ut $var1, $var2, "\n"; Den første utskriftssetningen vil skrives ut: 1111122222 Mens når vi utfører den andre utskriftssetningen, får vi strengen: 11111 22222
OBS Når du angir verdiene til spesialvariablene $\ og $, gjelder effekten deres for alle påfølgende kall til print()-funksjonen.
Hvis en filbeskrivelse ikke er spesifisert i utskriftsfunksjonen, utføres utdata som standard til standard utdatafil med STDOUT-beskrivelsen, og hvis utdatalisten ikke er spesifisert, vises innholdet i spesialvariabelen $_ . Standardinnstillingen for funksjonsbeskrivelse for print() kan endres med standard select()-funksjonen. Kalt uten parametere, returnerer den gjeldende standard utdatafilbeskrivelsen for funksjonene print() og write(). Hvis en enkelt parameter sendes til den, må den parameteren være en filbeskrivelse. I dette tilfellet returnerer den også gjeldende standardhåndtak og endrer det til håndtaket spesifisert av parameteren som er sendt til det. Et eksempel på bruk av select()-funksjonen er vist nedenfor. # Lagre gjeldende standardhåndtak og tilordne # F1 det nye standardhåndtaket $oldfilehandle = select(Fl); # Utdata til filen knyttet til Fl-beskrivelsen print $line; # Gjenopprett det gamle standardhåndtaket select($oldfilehandle); # Utdata til filen assosiert med den gamle beskrivelsen print $line; Som allerede nevnt, blir filer i Perl tolket som ustrukturerte strømmer av byte. Det med operasjonen<> og print()-funksjonen vi henholdsvis leser eller skriver en hel sekvens av byte, som vi kaller en "write", er på ingen måte assosiert med noen spesiell filstruktur. Det er bare at disse operasjonene er organisert på en slik måte at den ene leser, og den andre skriver sekvenser av byte. Faktisk kan vi lese og skrive informasjon til en fil byte for byte. For hver åpen fil opprettes det en systemvariabel som holder styr på dens nåværende posisjon, det vil si hvor i filen lesefunksjonene leser og skrivefunksjonene skriver informasjon. Derfor kan vi si at lese-/skriveoperasjoner utføres fra den nåværende posisjonen til filen. Enhver lese-/skriveoperasjon flytter pekeren for gjeldende filposisjon med antall byte som er lest eller skrevet. Hvis for eksempel en 80-byte-post har blitt lest helt fra begynnelsen av filen, vil neste lese- eller skriveoperasjon starte ved posisjon 81 byte av filen. For å bestemme gjeldende posisjon i filen, brukes tell()-funksjonen, den eneste parameteren som kan være en filbeskrivelse. Den returnerer gjeldende posisjon i filen knyttet til den gitte filbeskrivelsen. Den samme funksjonen uten en parameter returnerer gjeldende posisjon i filen som den siste leseoperasjonen ble utført for i programmet. Den nåværende posisjonen i filen endres automatisk i henhold til de utførte lese-/skriveoperasjonene, men den kan også endres eksplisitt ved å bruke seek()-funksjonen, som sendes en filbeskrivelse, en offset og et referansepunkt som parametere. For filen assosiert med beskrivelsen settes en ny gjeldende posisjon, forskjøvet med antall byte spesifisert av OFFSET-parameteren i forhold til referansepunktet: seek DETAILS, OFFSET, REFERENCE_POINT; REFERENCE_POINT-parameteren kan ha en av tre verdier: 0 - begynnelsen av filen, 1 - gjeldende posisjon, 2 - slutten av filen. Forskyvningen kan være enten positiv eller negativ. Det er negativt i forhold til slutten av filen, positivt i forhold til begynnelsen av filen, og kan enten være positivt eller negativt i forhold til gjeldende posisjon. Du kan også angi referansepunkter ved å bruke de navngitte konstantene SEEK_SET, SEEK_CUR og SEEK_END, definert i IO::Seekable-pakken som følger med Perl, som gjør programmet mer lesbart. Disse konstantene, i den rekkefølgen vi listet dem, tilsvarer begynnelsen av filen, gjeldende posisjon og slutten av filen. For å bruke disse navngitte konstantene, må du selvfølgelig inkludere denne modulen i programmet ved å bruke nøkkelordet bruk. For eksempel, følgende setninger setter de samme gjeldende filposisjonene: bruk IO::Seekable: seek FILE1, 5, 0; søk FIL2, 5, SEEK_SET; Språket har ingen spesielle funksjoner for å hoppe til begynnelsen eller slutten av en fil. Hvis du trenger å plassere filen på begynnelsen eller slutten, bør du bruke en nullforskyvning i forhold til de tilsvarende referansepunktene når du kaller seek()-funksjonen: seek FILE1, 0, 0; # Gå til begynnelsen av filsøk FILE1, 0, 2; # Hopp til slutten av filen I tillegg til de allerede kjente operasjonene med å lese filposter<> og readline(), gir Perl ytterligere to funksjoner for å lese innholdet i filer, getc() og read(). Den første leser en enkelt byte fra en fil, mens den andre leser poster med en gitt lengde, det vil si en sekvens av byte av en viss lengde. Getc()-funksjonen leser og returnerer tegnet ved den gjeldende posisjonen til filen hvis deskriptor sendes som en parameter, eller en udefinert verdi hvis slutten av filen nås eller det oppstår en feil. Hvis funksjonen kalles uten en parameter, leser den et tegn fra standard inndatafil STDIN. getc; # Les karakter fra STDIN getc F1; # Les tegnet ved den gjeldende filposisjonen # med F1-beskrivelsen. Read()-funksjonen leser et spesifisert antall byte, og starter på dens nåværende posisjon. Den kan kalles med tre eller fire parametere, og dens kall er: les DECRIPTOR, VARIABLE, LENGTH [,OFFSET]; Denne funksjonen leser antall byte spesifisert av heltallsverdien til LENGTH-parameteren inn i skalarvariabelen spesifisert av VARIABLE-parameteren fra filen med beskrivelsen spesifisert av den første DESCRIPTOR-parameteren. Returverdien er det faktiske antallet leste byte, 0 hvis du prøver å lese ved slutten av filen, og udefinert hvis andre feil oppstår. Den valgfrie parameteren OFFSET bestemmer etter hvilken byte av innholdet i variabelen VARIABLE posten lest fra filen vil bli lagret. Den kan også ha en negativ offset -n (n er et heltall). Dette betyr at de siste n bytene forkastes fra innholdet i variabelen VARIABLE og posten som leses fra filen legges til den gjenværende linjen. Listing 6.10 leser poster av en viss lengde fra en in.dat-fil som inneholder tre linjer med data: ******** * PERL * ******** Listing 6.10. Leser poster av en viss lengde #! perl -w open(F1, "in.dat") eller die "Feil ved åpning av fil: $!"; $str = "1234567890"; les F1, $str, 9; # Les ni byte inn i # variabel $str uten offsetutskrift $str,"\n"; # $str = "********\n" les F1, $str, 8, length($str); skriv ut $str,"\n"; # $str - "*******\n* PERL *" Oppføring 6-10 bruker funksjonen length() for å bestemme antall tegn (byte) i en skalarvariabel. Etter den første leseoperasjonen ble innholdet i $str-variabelen ødelagt fordi denne read()-funksjonen ble kalt uten forvirring. Ved den andre lesingen ble de lagrede dataene i $str-variabelen fullstendig lagret. Merk at nylinjetegnet i den første linjen i in.dat-filen også tas med i betraktningen når read()-funksjonen leser poster med en viss lengde. Du bør ikke glemme denne omstendigheten når du leser informasjon fra en "flerlinjes"-fil med lese ()-funksjonen.

Ubufret I/O

Funksjonene for å lese fra en fil sysread(), skrive til en fil syswrite() og sette gjeldende filposisjonspeker sysseek() er analoger av read(), print() og seek() funksjonene vi har vurdert, men, i motsetning til sistnevnte, har de direkte tilgang til de korresponderende systemoperasjonsfunksjonene, og ikke til standard C I/O-biblioteksfunksjoner, og omgår dermed bufferen som er opprettet av disse funksjonene for å utføre fillesing og skriving. Merk at det ikke er noen analog til den bufrede tell ()-funksjonen, dens funksjonalitet implementeres av sysseek ()-funksjonen. Når du kaller de ubuffrede lese- og skrivefunksjonene, sendes de det samme settet med parametere, som fullt ut svarer til parameterne til lesefunksjonen: sysread DECRIPTOR, VARIABLE, LENGTH [,OFFSET]; syswrite HANDLE, VARIABLE, LENGTH [,OFFSET]; Returverdien til disse funksjonene er det sanne antallet byte som er lest eller skrevet til filen, 0 hvis slutten av filen er nådd, eller undef hvis det oppstår en feil. Følgelig tilsvarer settet med parametere for sysseek()-funksjonen fullt ut parameterne som sendes til seek()-funksjonen: sysseek DESCRIPTOR, OFFSET, REFERANCE POINT; Alt som er sagt om bruken av seek()-funksjonen blir fullstendig overført til dens ubuffrede motpart. Funksjonaliteten til den bufrede tell()-operasjonen implementeres av følgende kall til sysseek()-funksjonen: $posisjon = sysseek Fl, 0, 1; # Gjeldende filpekerposisjon Programmet demonstrerer bruken av ubuffrede I/O-funksjoner for å behandle innholdet i en fil. #! perl -w bruk Fcntl; # Åpne filen i lese/skrivemodus sysopen F1, "in.dat", O_RDWR; # Les en blokk på 14 byte $read = sysread F1, $string, 14; advar "Les $read bytes i stedet for 14\n" hvis $read != 14; # Sett gjeldende posisjon (med 15 byte) $posisjon = sysseek Fl, 0, 1; die "Posisjonsfeil: $!\n" med mindre $posisjon er definert; # Skriv streng på gjeldende posisjon $string = "Ny verdi"; $written = syswrite F1, $string, length($string); die "Feil ved skriving: $!\n" hvis $skrevet != lengde($streng); # Lukk fil lukk F1 eller dø $!; Når du arbeider med ubuffrede I/O-funksjoner, bør du alltid se etter fullføringen av en lese-, skrive- eller posisjonsoperasjon. Standard I/O-systemet, som bufret I/O implementeres gjennom, kontrollerer selv fullføringen av de spesifiserte operasjonene og er ansvarlig for det hvis prosessen av en eller annen grunn ble avbrutt midt i en skriving. Med ubuffret I/O må programmereren ta seg av dette.