Thread bitte um Hilfe bei Optimierung eines Skripts (7 answers)
Opened by McSvenster at 2008-11-19 00:38

McSvenster
 2008-11-19 00:38
#116380 #116380
User since
2008-11-19
12 Artikel
BenutzerIn
[default_avatar]
Hallo allerseits,

ich fange mit Perl erst an und bin für jeden Tipp dankbar. Ich möchte eine große Textdatei (350 MB nur Text!) in XML- Files überführen und habe einen Parser geschrieben. Die Textdatei hat folgenden Aufbau:

Code: (dl )
Nummer Feldname Feldinhalt


Die Nummer wird für jedes Feld wiederholt, Felder können sich auch wiederholen. Die Datei sieht etwa so aus:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
000000001 020 irgendetwas
000000001 020 irgendetwas anderes
000000001 021 irgendetwas
000000001 300 irgendetwas
000000001 301 irgendetwas
000000001 301 irgendetwas anderes
000000001 301 irgendetwas XYZ
000000001 650 irgendetwas
000000002 020 irgendetwas
000000002 021 irgendetwas
000000002 100 irgendetwas
000000002 300 irgendetwas
...


Ich möchte für jede Nummer ein XML-File anlegen (oder wäre ein grosses XML für alle Nummern sinnvoller?). Mein Skript sieht so aus:

Code (perl): (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
#!/usr/bin/perl
$dumpfile = "pfad_zum_TextFile";
#
# 1. Hash mit Systemnummern bilden, damit jede Nummer nur einmal vorkommt.
# (Die Anzahl der Vorkommen kann vielleicht spaeter noch genutzt werden.)
#
open (katalog,"$dumpfile") || die "Der Dump kann nicht geoeffnet werden.";
while (defined($Zeile = <katalog>)){
        $SysNummern{substr($Zeile,0,9)} = $SysNummern{substr($Zeile,0,9)} +1; 
        }
close (katalog);
# 2. Hash in Array überführen
for $Nummern(sort keys %SysNummern){
        push @Systemnummern, $Nummern;
}
$letzteNummer = $Systemnummern[-1];
# 3. für jede Systemnummer im Array loslegen
foreach $Nummer (@Systemnummern){
        print "Nummer $Nummer von $letzteNummer\n";
        open (karteikarte,">./output/$Nummer.xml") || die "kann xml nicht schreiben - vielleicht kein Verzeichnis output vorhanden?";
        print karteikarte "<add><doc>\n";
        print karteikarte "<field name=\"id\">$Nummer</field>\n";
        open (katalog,"$dumpfile");
        while (defined($Zeile = <katalog>)){
                if (substr($Zeile,0,9) == $Nummer){
                        $Feldname = substr($Zeile,10,5);
                        $Feldinhalt = substr($Zeile,21);
                        chomp $Feldinhalt;
                        print karteikarte "<field name=\"$Feldname\">$Feldinhalt</field>\n";
                }
                elsif (substr($Zeile,0,9) > $Nummer){
                        print karteikarte "</doc></add>\n";
                        close (karteikarte);
                        last;
                }
        }
        close (katalog);
}


Wie Ihr sehen könnt, dauert es einen kleinen Moment, bis der Hash aufgebaut und in das Array überführt ist (ist das sinnvoll so?), dann gehen die ersten Nummern rasend schnell. Bis etwa 1000 geht es gut, dann wird die Verarbeitung schon merklich langsamer, da das Skript jedes Mal erst bis zur passenden Nummer hoch zählt.

Hier gibt es doch bestimmt eine elegantere Lösung, oder? Ich muss ca. 400.000 Nummern abarbeiten (= XML- Files anlegen).

Danke schonmal für Eure Hilfe!
Sven

View full thread bitte um Hilfe bei Optimierung eines Skripts