PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [Perl] Referenz auf Filehandels



Caveman
13-03-2006, 10:48
Hallo *,

ich möchte in Perl einen Filehandler als Referenz abspeichern, da ich den in mehreren Funktionen brauche.

So wie hier funktioniert es leider nicht :(

#!/usr/bin/perl -w

use strict;
use warnings;

sub new # Konstruktor
{
my $this = shift;
my $class = ref($this) || $this;
my $path = shift;
my $name = shift;

my $self = {
filehandler => \*DATA,
};

bless $self, $class;

open( $self->{filehandler}, "<$path$name" ) ||
die "Datei " . $name . " kann nicht geoeffnet werden";

return $self;
}

sub getLines # Zeilen einlesen
{
my $self = shift;
my @line;

while ( $self->{filehandler} ) #### funktioniert so nicht ####
{
s/#.+//; # Kommentare entfernen
s/^\s+//; # Leerzeichen am Anfang entfernen
s/\s+$//; # Leerzeichen am Ende entfernen
if ( /^__END__/ )
{ # Ende des Datenbereichs erreicht
last;
}
if ( /^./ )
{ # wenn Zeile nicht leer ist
$line[++$#line] = $_;
}
}

return \@line;
}

sub DESTROY # Destruktor
{
my $self = shift;

close( $self->{filehandler} );
}

my $fileRead = main->new("./", "testfile.txt"); # Konstruktor aufrufen
my $lines = $fileRead->getLines(); # Datei zeilenweise holen

foreach my $line ( %{$lines} )
{
print "$line\n"; # Ausgabe
}

1;

__END__
Wie mache ich es richtig?

Edit:
Auch mit dieser Zeile mag es nicht funktionieren:

while ( "<" . $self->{filehandler} . ">" )

michael.sprick
13-03-2006, 11:33
Hi,

zunächst mal zum Konstruktor:



sub new # Konstruktor
{
my $this = shift;
my $class = ref($this) || $this;
my $path = shift;
my $name = shift;

my $self = {
filehandler => \*DATA,
};

bless $self, $class;

open( $self->{filehandler}, "<$path$name" ) ||
die "Datei " . $name . " kann nicht geoeffnet werden";

return $self;
}



filehandler => \*DATA, kannst du Dir sparen. Zum einen gibts ja noch garkein DATA, was Du zuweisen könntest, zum anderen initialisierst du $self->{filehandler} ja eh in der open() Anweisung... Es genügt also ein einfaches:



my $self = {
filehandler => undef
};



Um von dem Handle zu lesen benutzt Du die readline() Funktion... also




while(readline($self->{filehandler})
{
print;
}



Sonst landest Du in einer Endlosschleife weil $self->{filehandler} ja wohldefiniert ist und auch bleibt...

Was ich noch nicht verstanden habe, ist der Inhalt dieser while-Schleife.
Wozu das zweidimensionale Array? Warum gibst Du eine Referenz auf das lokale Array zurück und warum derefenzierst Du später als Hash?

Wenn Du nicht etwas ganz spezielles damit erreichen willst, dürfte folgendes wohl die syntaktisch korrektere Lösung sein:



my @line;
while(readline($self->{filehandler}))
{
#tu was
if ( /^./ )
{ # wenn Zeile nicht leer ist
push(@line, $_);
}
}
return(@line);



und



my @lines = $fileRead->getLines();
foreach(@lines)
{
print;
}


soweit, hth,

Michael

Caveman
13-03-2006, 13:47
Danke, mit readline() funktioniert's :)

Ich habe die Zeile
filehandler => *DATA,
ganz entfernt und habe in die while-Schleife
readline($self->{filehandler})
eingetragen.

Zu dem war noch ein kleiner Fehler in der foreach-Schleife der Ausgabe:
Hier muss natürlich statt diesem:
foreach my $line ( %{$lines} )
das:
foreach my $line ( @{$lines} )
stehen (Also Array statt Hash)

Auch habe ich
push(@line, $_);
statt
$line[++$#line] = $_;
eingesetzt, was allerdings nichts ändert (funktioniert beides).

Als Referenz geb ich das Array deshalb zurück, weil ich keine Kopie haben möchte.
Die Daten werden in einer anderen Klasse noch weiter verarbeitet und dann in deren Klassenvariable abgelegt.