Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]7401[/thread]

Auslesen aus .txt bis Trennzeichen, wie?: Auslesen aus .txt bis Trennzeichen, wie? (Seite 6)



<< |< 1 ... 3 4 5 6 >| >> 52 Einträge, 6 Seiten
Dubu
 2005-11-10 18:02
#59393 #59393
User since
2003-08-04
2145 Artikel
ModeratorIn + EditorIn

user image
Code: (dl )
#!D:/Programme/Perl -w

Wenn du "use warnings" drin hast, solltest du das "-w" weglassen. Naeheres siehe perllexwarn.

Code: (dl )
1
2
3
4
5
6
7
8
use strict;
use warnings;
use Text::CSV_XS;

my @fields;
my $geparst;
my @geparst;
my $i;

Diese Variablen brauchst du entweder gar nicht oder zumindest nicht hier. Variablen immer im kleinstmoeglichen Bereich deklarieren (Schleifenvariablen z.B. nur in der Schleife).

Code: (dl )
1
2
3
4
5
6
7
8
9
my $file = 'apo_neu-1.csv';
my @entries;

my $parser = Text::CSV_XS->new({sep_char => ';',
  'binary' => 1
  });

open(DATEI,">datei.txt") or die $!;
open(my $fh,"<$file") or die "File apo_neu-1.csv nicht gefunden";

Nicht gefunden ist eine Moeglichkeit. Der wahre Grund steht aber in $!, deshalb sollte man sich den Inhalt dieser Variable bei Fehlern mit ausgeben lassen:
open (...) or die "Fehler beim Oeffnen: $!";

Code: (dl )
1
2
3
while (my $line = <$fh>)
{
    if($parser->parse($line))

Zu diesem if (...) fehlt eine else-Zweig: Was soll passieren, wenn eine Zeile nicht geparst werden kann? Vgl. pqs Kommentar oben.

Code: (dl )
1
2
3
4
5
6
7
8
    {
        @fields = $parser->fields();
        
        if ($fields[-1] =~ m/^\d{2}$/ and $fields[-1] > 0 and $fields[-1] <= 49)   # Nur Zahlen von 01 bis 49
        {       ; 
            my $geparst = join (' ',@fields);
            @geparst = $geparst;
            print DATEI $_,"\n" for(@geparst);

Warum so umstaendlich?
Du fasst alle Felder aus @fields zum Skalar $geparst zusammen, weist diesen dann dem Array @geparst zu (das somit nur ein Element enthaelt) und gibst dieses Array dann in DATEI aus - mit einer Schleife ueber genau ein Element.
Das ginge kuerzer mit:
print DATEI join (' ', @fields), "\n";

Code: (dl )
1
2
3
4
5
6
7
8
9
10
        }
    
    }
}
close $fh;
close (DATEI);

open(DATEI,"datei.txt") || die "File datei.txt nicht gefunden";
@geparst = <DATEI>;
close(DATEI);

Aeh ... was soll das denn?
Du schreibst erst die unsortierten Daten in "datei.txt", um sie dann gleich wieder aus der Datei auszulesen, im Anschluss zu sortieren und dann nochmal in "datei.txt" zu schreiben?? Und brauchst du diese Datei danach ueberhaupt nochmal?

Warum speicherst du nicht gleich in der Schleife oben in das Array @geparst, statt in die Datei?
           push @geparst, join (' ',@fields);


Code: (dl )
1
2
3
4
5
6
my @sorted = map{$_->[0]}sort{$a->[1]->[-1] <=> $b->[1]->[-1]}map{[$_,[split(/ /,$_)]]}@geparst;  # Sortieren nach dem letzten Arrayfeld
my $anzahl = @sorted;

open(DATEI,">datei.txt") || die $!;
print DATEI $_ for(@sorted);
close(DATEI);

Okay, wofuer auch immer du die Datei brauchst ...

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
#-----------------------------------------------------------------------------------------
# Aufteilen der Daten auf 6 Server
#-----------------------------------------------------------------------------------------

open(SERVER1,">apo_server1.txt") || die "Datei apo_server1.txt nicht gefunden";
for($i=0; $i<$anzahl;)
{
    print SERVER1 $sorted[$i];
    $i += 6;
}
close(SERVER1);

[...etc...]

Uh, das ist wirklich boese. Sechsmal fast identischer Code. Den koennte man wirklich gut zusammenfassen:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
# Aufteilen auf $servercnt Server
my $servercnt = 6;
my @servers;
for my $s (0 .. $servercnt-1) {
   open ($servers[$s], '>', "apo_server" . $s+1 . ".txt")
       or die "Konnte Datei apo_server" . $s+1 . ".txt nicht zum Schreiben oeffnen: $!";
}
my $act_server = 0;
for my $i (0 .. $anzahl) {
   print $servers[$act_server] $sorted[$i];   # Zeile fuer Server Nr. $act_server+1 ausgeben
   $act_server = ($act_server+1 % $servercnt);   # naechster Server
}
close $_ for @servers;

(ungetestet)

Edit: ungetestet und falshc. Das mit dem indirekten Filehandle hinter print klappt so nicht (wie ich schon befuerchtete) und beim Modulo fehlen Klammern. Siehe den verbesserten Code in meinem naechsten Beitrag.\n\n

<!--EDIT|Dubu|1131640430-->
Dubu
 2005-11-10 18:24
#59394 #59394
User since
2003-08-04
2145 Artikel
ModeratorIn + EditorIn

user image
Hier ein soweit funktionierender Code (mit deinen Daten getestet) mit den genannten Verbesserungen.
Ich habe dabei - wie ich es meist mache - die globalen Variablen mit Grossbuchstaben am Wortanfang benannt, damit sie leichter von den lokalen zu unterscheiden sind, ein paar Warnungen ergaenzt und umgeschrieben und weniger hartkodierte Werte benutzt (Dateiname, Serveranzahl).
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
42
43
44
45
46
47
48
49
50
51
52
53
#!/usr/bin/perl

use strict;
use warnings;
use Text::CSV_XS;

my $File = 'apo_neu-1.csv';
my $ServerCnt = 6;
my @Entries;

my $Parser = Text::CSV_XS->new({
   sep_char    => ';',
   binary      => 1,
});

open (my $InFile,'<', $File) or die "Konnte $File nicht oeffnen: $!";

while (my $line = <$InFile>) {
   if($Parser->parse($line)) {
       my @fields = $Parser->fields();

       # Nur Zahlen von 01 bis 49 im letzten Feld erlaubt
       if ($fields[-1] =~ m/^\d{2}$/ and $fields[-1] > 0 and $fields[-1] <= 49) {
           push @Entries, [ @fields ];
       }
   } else {
       warn "Fehler beim Parsen in Zeile $. (Inhalt: " . $Parser->error_input() . ")";
   }
}

# Sortieren nach dem letzten Arrayfeld
my @Sorted = sort {$a->[-1] <=> $b->[-1]} @Entries;

#-----------------------------------------------------------------------------------------
# Aufteilen der Daten auf $ServerCnt Server
#-----------------------------------------------------------------------------------------

my @Servers;
for my $s (0 .. $ServerCnt-1) {
   open ($Servers[$s], '>', "apo_server" . ($s+1) . ".txt")
       or die "Konnte Datei apo_server" . ($s+1) . ".txt nicht zum Schreiben oeffnen: $!";
}
my $ActServer = 0;
for my $i (0 .. $#Sorted) {
   # Zeile fuer Server Nr. $act_server+1 ausgeben
   print { $Servers[$ActServer] } join(" ", @{$Sorted[$i]}), "\n";

   # Naechster Server
   $ActServer = (($ActServer+1) % $ServerCnt);
}
close $_ for @Servers;

#-----------------------------------------------------------------------------------------
<< |< 1 ... 3 4 5 6 >| >> 52 Einträge, 6 Seiten



View all threads created 2005-10-26 14:09.