Schrift
[thread]8200[/thread]

Filehandler über Array?!

Leser: 1


<< >> 9 Einträge, 1 Seite
rucksl
 2006-07-25 20:52
#68390 #68390
User since
2004-06-15
13 Artikel
BenutzerIn
[default_avatar]
Hallo,

ich möchte mehrere Dateien in Perl öffnen. Die Anzahl steht noch nicht fest und wird dynamisch beim Programmlauf entschieden.
Die Inhalte der Dateien werden ausgelesen und zusammengefügt.

Deshalb meine kurze Frage. Ist es die durch z.B. open(IN0, $inputfiles[0]) or die "Cannot open inputfile $inputfiles[0]"; geöffnete Files möglich den Filehandler in ein zu packen und als Ersatz für $text = <IN0> irgendwas mit einem Array zu machen???

Hoffe jemand kann mir weiterhelfen. Hab nun schon ewig gesucht Traurig

Gruß
Marc
Linuxer
 2006-07-25 22:44
#68391 #68391
User since
2006-01-27
3872 Artikel
HausmeisterIn

user image
[quote=rucksl,25.07.2006, 18:52]Hab nun schon ewig gesucht[/quote]
Auch in der Perldoc?

perldoc -f open:

Quote
...
If FILEHANDLE is an undefined scalar variable (or array or hash element) the variable is assigned a reference to a new anonymous filehandle, ...


Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/perl
# vi:ts=4 sw=4 et:
use strict;
use warnings;

my @handles = ();

for ( 0 .. $#ARGV ) {

open $handles[$_], $ARGV[$_] or die "$ARGV[$_]: $!\n";

}

print scalar(@handles) . " open Filehandles\n";


edit: Die Inhalte der Handles kannst Du z.B. dann so zusammenführen:
Code: (dl )
1
2
my $text = join( '', map { local $/; <$_> } @handles );
print $text, $/;
\n\n

<!--EDIT|Linuxer|1153853957-->
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
topeg
 2006-07-25 22:47
#68392 #68392
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
klar aber es funktioniert etwas anders:
Code: (dl )
open($hande,'*',$filename)
* steht hier für die üblichen öffnungsvarianten wie z.B. ">" oder "<"
mal als Beispiel:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!usr/bin/perl
use strict;
my @files=();
push(@files,{name=>'./test.txt' open=>">", $fh=>''});
push(@files,{name=>'./test2.txt' open=>"<", $fh=>''});
push(@files,{name=>'./test3.txt' open=>">>", $fh=>''});
for my $i (@files)
{
open($i->{fh},$i->{open},$i->{name}) or die "Fehler $!\n";
}
# mach irgendwas mitr den Dateihandles
for my $i (@files)
{
close($i->{fh}) or die "Fehler $!\n";
}


Aber warum speicherst du den Inhalt der Dateien nicht in Variablen zwischen? Dann wird die Abarbeitung auch schneller, da das lesen/schreiben einer Datei immer einige Zeit in Anspruch nimmt.
sid burn
 2006-07-26 00:13
#68393 #68393
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Hmm, ich weiß nicht so ganz ob das eine ganz Optimale Lösung ist, jedenfalls stand im Alpaka Buch das man IO::File nutzen sollte, wenn man eine Referenz auf ein Dateihandle erstellen möchte. Dieses Referenz könntest du dann natürlich auch nutzen und die Referenzen einem Array hinzufügen.

Code: (dl )
1
2
3
4
5
use IO::File;

my @files;
map {push @files, IO::File->new("$_")} qw/foo.txt bar.txt/;
map {print <$_>} @files;


Allerdings ist mir aufgefallen das ein "print <$files[0]>" nicht klappt, und er gibt dann die blessed Referenz aus. Du musst also die Referenz wieder wie oben gezeigt in ein einzelnes Skalar Speichern und es dann als Dateihandle benutzen.\n\n

<!--EDIT|sid burn|1153858482-->
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
rucksl
 2006-07-26 00:22
#68394 #68394
User since
2004-06-15
13 Artikel
BenutzerIn
[default_avatar]
Hi, DANKE für die Infos!!!!

Habs jetzt hinbekommen mit euerer Hilfe!!
VIELEN DANK!\n\n

<!--EDIT|rucksl|1153860630-->
sid burn
 2006-07-26 00:46
#68395 #68395
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Naja im Grunde genommen lief mein Code so wie du es zuletzt geschrieben hast, nur habe ich ein map anstatt eine for Schleife genommen, du kannst das map aber auch wieder in einer for Schleife umwandeln.

Code: (dl )
1
2
3
4
5
6
7
8
9
use IO::File;

my @files;
map {push @files, IO::File->new("$_")} qw/foo.txt bar.txt/;

for my $file (@files) {
my $line = <$file>;
print "Das ist $line.\n";
}

Gibt dann von jeder Datei die erste Zeile aus. Oder du benutzt ganz die OOP Schreibweise.

Code: (dl )
1
2
3
for my $file (@files) {
$line = $file->getline;
}


Bei der OOP Schreibweise wie ich gerade sehe kannst du es auch so schreiben:

Code: (dl )
my $line = $files[0]->getline;

Gibt dann die erste Zeile aus der ersten Datei wieder.


IO::File erbt von IO::Handle und IO::Seekable, daher du kannst auch die Methoden benutzen die dort stehen.

http://perldoc.perl.org/IO/File.html
http://perldoc.perl.org/IO/Handle.html
http://perldoc.perl.org/IO/Seekable.html\n\n

<!--EDIT|sid burn|1153860469-->
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
rucksl
 2006-07-26 00:52
#68396 #68396
User since
2004-06-15
13 Artikel
BenutzerIn
[default_avatar]
Sorry, jetzt war ich wohl zu langsam :-)

Danke für die Info. Ist super.

Der Tipp mit dem OO Ansatz gefällt mir sehr gut. Werds gleich mal ausprobieren :-)
topeg
 2006-07-26 01:15
#68397 #68397
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Allso hier mal beide Varianten nebeneinander gestellt.

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/usr/bin/perl
use strict;
use IO::File;

my @files=();
push(@files,{name=>'/tmp/txt1.txt', nopen=>"r", open=>"<", fh=>undef, nfh=>''});
push(@files,{name=>'/tmp/txt2.txt', nopen=>"r", open=>"<", fh=>undef, nfh=>''});
push(@files,{name=>'/tmp/txt3.txt', nopen=>"r", open=>"<", fh=>undef, nfh=>''});
push(@files,{name=>'/tmp/txt4.txt', nopen=>"r", open=>"<", fh=>undef, nfh=>''});
push(@files,{name=>'/tmp/txt5.txt', nopen=>"r", open=>"<", fh=>undef, nfh=>''});

for my $i (@files)
{
# ALT
open($i->{fh},$i->{open},$i->{name}) or die "Fehler $!\n";

# NEU ( Objektorienetiert )
$i->{nfh}=IO::File->new($i->{name},$i->{nopen}) or die "Fehler $!\n";
}

for my $i (@files)
{
# ALT
# my $txt=readline($i->{fh}); #<= Alternativ
my $fh=$i->{fh};
my $txt=<$fh>;
print "ALT: $i->{name}: $txt\n";

# NEU
my $ntxt=$i->{nfh}->getline();
print "NEU: $i->{name}: $ntxt\n";
}

for my $i (@files)
{
# ALT
close($i->{fh}) or die "Fehler $!\n";

# NEU
$i->{nfh}->close() or die "Fehler $!\n";
}
Strat
 2006-07-26 14:08
#68398 #68398
User since
2003-08-04
5246 Artikel
ModeratorIn
[Homepage] [default_avatar]
[quote=sid burn,25.07.2006, 22:13]... jedenfalls stand im Alpaka Buch das man IO::File nutzen sollte, wenn man eine Referenz auf ein Dateihandle erstellen möchte...[/quote]
Dieses Buch ist auch schon ein paar Jahre alt. Dieser Weg funktioniert gut, aber mittlerweile wuerde ich den folgenden Weg (wurde eh schon so aehnlich genannt) waehlen:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
my @FHs = ();
for my $i (0..$#ARGV) { # fuer jeden uebergebenen Parameter
open( $FHs[$i], "<", $ARGV[$i] )
or die "Error: couldn't open file '$ARGV[$i]': $!\n";
} # for

# z.B. alles in ein array einlesen
my @array = ();
foreach my $FH (@FHs) {
push( @array, <$FH> );
close( $FH ); # nicht mehr benoetigten FH schliesen
} # for

# array entsorgen, wenn da eh nichts mehr offen ist
undef( @FHs );
\n\n

<!--EDIT|Strat|1153908572-->
perl -le "s::*erlco'unaty.'.dk':e,y;*kn:ai;penmic;;print"
http://www.fabiani.net/
<< >> 9 Einträge, 1 Seite



View all threads created 2006-07-25 20:52.