Ooops
Etwas wie
open TMPFILE ">/tmp/work.$$"; print TMPFILE ...
ist praktisch immer ein Programmierfehler. Hier wird zum Einen der unsichere Aufruf von open() mit zwei Argumenten statt der sichereren Form mit drei Argumenten verwendet und zum Anderen ist das Muster zur Erzeugung der temporären Datei viel zu einfach.
Bordmittel sind reichlich vorhanden
Perl stellt zur Erzeugung temporärer Dateien einige sichere Methoden zur Verfügung, z.B. anonyme temporäre Dateien und das Standardmodul File::Temp.
Anonyme temporäre Dateien
Seit Perl 5.8 besteht die Möglichkeit anonyme temporäre Dateien zu erzeugen, indem open() anstelle eines Dateinamens undef als Parameter übergeben wird.
Beispiel:
#!/usr/bin/perl use strict; use warnings; my $fh; open($fh,"+>",undef) or die "Could not open temp file - $!"; # Daten in Temp-Datei schreiben foreach my $line ( 1 .. 5 ) { print $fh "$line\n"; } # Daten aus Temp-Datei lesen # Zum Anfang der Datei seek($fh, 0, 0); while(<$fh>) { print; } close($fh) or die "Could not close temp file - $!"; exit();
File::Temp
File::Temp ist seit Perl 5.6.1 ein Standardmodul, d.h. es wird mit Perl ausgeliefert und läuft auf jeder Plattform, die von Perl unterstützt wird.
Dokumentation und API werden selbst von sehr gutmütigen Menschen bestenfalls als verwirrend bezeichnet.
Nachfolgend einige Beispiele, die Ihnen den Einstieg in File::Temp schrittweise erleichtern sollen.
Beispiel 1
Dieses Beispiel verwendet die Standardwerte von File::Temp.
#!/usr/bin/perl use warnings; use strict; use File::Temp qw/ tempfile tempdir /; my ($dir, $fh, $filename, $line); $dir = tempdir( CLEANUP => 1 ); ($fh, $filename) = tempfile( DIR => $dir ); binmode($fh); print "Verzeichnis: $dir\n"; print "Datei: $filename\n"; # Daten in Temp-Datei schreiben foreach $line ( 1 .. 5 ) { print $fh "$line\n"; } # Daten aus Temp-Datei lesen # Zum Anfang der Datei seek($fh,0,0); while ($line = <$fh>) { print $line; } exit();
Ausgabe unter Linux
Verzeichnis: /tmp/ZT4Udprbvy Datei: /tmp/ZT4Udprbvy/4DOBscRn7o 1 2 3 4 5
Ausgabe unter Windows
Verzeichnis: C:\DOKUME~1\tf\LOKALE~1\Temp\LzIqqKVIga Datei: C:\DOKUME~1\tf\LOKALE~1\Temp\LzIqqKVIga\SL1tNeuIvV 1 2 3 4 5
File::Temp schreibt nicht einfach in eine Datei mit zufällig gewähltem Dateinamen, sondern legt zunächst ein Verzeichnis mit zufällig gewähltem Namen an, in dem dann die Datei angelegt wird.
Die Anweisung
$dir = tempdir( CLEANUP => 1 );
sorgt dafür, das das temporäre Verzeichnis einschließlich der darin enthaltenen Dateien beim Beenden des Programms komplett gelöscht wird. Dieses Verhalten kann abgeschaltet werden durch
$dir = tempdir( CLEANUP => 0 );
Aufräumen müssen Sie jetzt selbst.
Beispiel 2: Verzeichnis für temporäre Dateien festlegen
Wer vermeiden möchte, das File::Temp temporäre Dateien unterhalb der systemüblichen Verzeichnisse anlegt, z.B. wenn /tmp auf einer anderen Partition oder Festplatte liegt oder bei "Shared Webhosting", kann ein (bereits bestehendes) Verzeichnis über den Parameter DIR als Speicherort festlegen.
#!/usr/bin/perl use warnings; use strict; use File::Temp qw/ tempfile tempdir /; my ($dir, $mydir, $fh, $filename); $mydir = './mydir'; mkdir $mydir unless -d $mydir; $dir = tempdir( DIR => $mydir, CLEANUP => 0 ); ($fh, $filename) = tempfile( DIR => $dir ); print "Verzeichnis: $dir\n"; print "Datei: $filename\n"; exit();
Das Programm erzeugt folgende Ausgabe:
Verzeichnis: mydir/2bQHkxZFqY Datei: mydir/2bQHkxZFqY/lKyMkclvzR
Beispiel 3: Extension für Dateinamen setzen
Dateiendungen lassen sich über den Parameter SUFFIX festlegen.
#!/usr/bin/perl use warnings; use strict; use File::Temp qw/ tempfile tempdir /; my ($dir, $mydir, $fh, $filename, $suffix); $mydir = './mydir'; mkdir $mydir unless -d $mydir; # Dateiendung festlegen $suffix = '.tmp'; $dir = tempdir( DIR => $mydir, CLEANUP => 0 ); ($fh, $filename) = tempfile( DIR => $dir, SUFFIX => $suffix, ); print "Verzeichnis: $dir\n"; print "Datei: $filename\n"; exit();
Das Programm erzeugt folgende Ausgabe:
Verzeichnis: mydir/SmAZ7Dj9AO Datei: mydir/SmAZ7Dj9AO/eyi7h7fT0l.tmp
Beispiel 4: Länge des Dateinamens festlegen
File::Temp legt automatisch zufällige Dateinamen der Länge 10 an. Die Länge des Dateinames lässt sich durch Übergabe eines Templates als ersten Parameter an tempfile() ändern. Der Großbuchstabe X wird als Platzhalter für zufällige, von File::Temp erzeugte Buchstaben, Ziffern und Sonderzeichen verwendet.
#!/usr/bin/perl use warnings; use strict; use File::Temp qw/ tempfile tempdir /; my ($dir, $mydir, $fh, $filename, $suffix, $template); $mydir = './mydir'; mkdir $mydir unless -d $mydir; # Dateiendung festlegen $suffix = '.tmp'; # Dateinamen anpassen # 12 zufällige Elemente (X) $template = 'tmp_XXXXXXXXXXX'; $dir = tempdir( DIR => $mydir, CLEANUP => 1 ); ($fh, $filename) = tempfile($template, DIR => $dir, SUFFIX => $suffix, ); print "Verzeichnis: $dir\n"; print "Datei: $filename\n"; exit();
Das Programm erzeugt folgende Ausgabe:
Verzeichnis: mydir/73vWvvqRno Datei: mydir/73vWvvqRno/tmp_qzbFzrot_fe.tmp
Beispiel 5: Objektorientierung
File::Temp bietet neben der bereits gezeigten prozeduralen auch eine objektorientierte Schnittstelle an.
Das oben gezeigte Beispiel 4 lässt sich wie folgt auch objektorientiert schreiben.
#!/usr/bin/perl use warnings; use strict; use File::Temp; my ($dir, $mydir, $fh, $filename, $suffix, $template); $mydir = './mydir'; mkdir $mydir unless -d $mydir; # Temp-Verzeichnis unterhalb von $mydir erzeugen $dir = File::Temp->newdir( DIR => $mydir, CLEANUP => 1, ); # Dateiendung festlegen $suffix = '.tmp'; # Dateinamen anpassen # 12 zufällige Elemente (X) $template = 'tmp_XXXXXXXXXXX'; $fh = File::Temp->new( TEMPLATE => $template, DIR => $dir, SUFFIX => $suffix, ); print "Verzeichnis: ", $dir->dirname(), "\n"; print "Datei: ", $fh->filename(), "\n"; exit();
Ausgabe wie in Beispiel 4.
Jetzt kommentieren