Sascha: Datei teilweise einlesen

Hallo,

ich habe eine Text-Datei mit Mitgliederinformationen (feste Feldlängen).

Nun habe ich ein kleines Perl proggi welches diese Datei einliest, unnötige Felder rauslöscht, Leerzeichen am Satzende entfernt, ein Semikolon als Trennzeichen einfügt und dann unter anderem Namen abspeichert.

Nun hat sich die Eingangsdatei dramatisch vergrößert (Text-Datei hat etwa 930 MB, ca. 2.5 Mil. Zeilen).

Es sollen nun mehrere Ausgangsdateien geschrieben werden, die erste z.B. von Mitglied 00000001 - 00100000, die nächste von 00100001 - 00200000 usw....

Mein altes Proggi bringt meinen Rechner gnadenlos in den Speicherüberlauf.

Wie kann ich es nun schaffen, das nur der erste Block an Daten eingelsen wird, korregiert und abgespeichert wird, und dann der nächste Block erst wieder an der Stelle anfängt einzulesen an der der erste Block zu ende war?
Kann ich einen offset einstellen (ich weiss ja z.B. das eine Zeile immer genau 422 Zeichen besteht)?

Danke für alle Tips!

Sascha

  1. 你好 Sascha,

    Mein altes Proggi bringt meinen Rechner gnadenlos in den Speicherüberlauf.

    Vermutlich, weil du ein “@lines = <FILE>”-Konstrukt hast? Sinnvoller waere
    da ein

    while(my $line = <FILE>) {
      # mach was mit $line
    }

    Wie kann ich es nun schaffen, das nur der erste Block an Daten eingelsen
    wird, korregiert und abgespeichert wird, und dann der nächste Block
    erst wieder an der Stelle anfängt einzulesen an der der erste Block zu
    ende war?
    Kann ich einen offset einstellen (ich weiss ja z.B. das eine Zeile immer
    genau 422 Zeichen besteht)?

    Ich glaube, du suchst seek und tell.

    再见,
     CK

    --
    Mit einem Windhauch kannst du das Feuer loeschen. Mit einem Windhauch kannst du das Feuer entfachen.
    http://wwwtech.de/
    1. Hallo

      你好 Sascha,

      Mein altes Proggi bringt meinen Rechner gnadenlos in den Speicherüberlauf.

      Vermutlich, weil du ein “@lines = <FILE>”-Konstrukt hast? Sinnvoller waere
      da ein

      while(my $line = <FILE>) {
        # mach was mit $line
      }

      ...Das war mein erster Fehler...

      Wie kann ich es nun schaffen, das nur der erste Block an Daten eingelsen
      wird, korregiert und abgespeichert wird, und dann der nächste Block
      erst wieder an der Stelle anfängt einzulesen an der der erste Block zu
      ende war?
      Kann ich einen offset einstellen (ich weiss ja z.B. das eine Zeile immer
      genau 422 Zeichen besteht)?

      Ich glaube, du suchst seek und tell.

      再见,
      CK

      AHA! Genau nachdem habe ich gesucht. Habe es auch gleich ausprobiert. Klappt prima, BIS AUF DIESEN FEHLER: die erste Datei stimmt einwandfrei, bei der 2. Datei fehlt die 1. Zeile! Der Datensatz ist dann in keiner der beiden Dateien vorhanden!

      Hab hier mal ein Auszug von dem wie es etwa bei mir aussieht:

      sysopen (DATEI, $data2 , O_RDONLY);

      while(<DATEI>)
      {
        #Felder definieren, korregieren usw...
        if ($feld1 <= $dat1)               #1er Block
               {push(@NeueZeilen,$neu);}
        else                               # Block 1 zuende
               {$pos = tell (DATEI); close (DATEI);}
      }

      open(DAT, ">$dfs1") # Schreibe Ausgangsdatei 1
      print DAT @NeueZeilen;
      close (DAT);

      sysopen (DATEI, $data2 , O_RDONLY);
      seek (DATEI,$pos,0);                 # Position setzen
      while(<DATEI>)
      {
        #Felder definieren, korregieren usw...
        if ($feld1 <= $dat1) #2er Block
               {push(@NeueZeilen,$neu);}
               else {$pos = tell (DATEI); close (DATEI);}
      }
      open(DAT, ">$dfs2") # Schreibe Ausgangsdatei 2
      print DAT @NeueZeilen;
      close (DAT);

      Woran liegt das ??? Ich habe auch schon von $pos-1 probiert, das war es aber nicht :-)

      Danke

      Sascha

      1. Hab hier mal ein Auszug von dem wie es etwa bei mir aussieht:

        sysopen (DATEI, $data2 , O_RDONLY);

        while(<DATEI>)
        {
          #Felder definieren, korregieren usw...
          if ($feld1 <= $dat1)               #1er Block
                 {push(@NeueZeilen,$neu);}
          else                               # Block 1 zuende
                 {$pos = tell (DATEI); close (DATEI);}
        }

        Du pushst hier evtl. 900MB in den Speicher. Warum?

        Du kannst ohne Probleme zwei Dateien gleichzeitig öffnen (oder mehr), eine zum lesen und eine zum schreiben.

        Struppi.

        1. Du pushst hier evtl. 900MB in den Speicher. Warum?

          Keine Ahnung...

          Du kannst ohne Probleme zwei Dateien gleichzeitig öffnen (oder mehr), eine zum lesen und eine zum schreiben.

          ist geändert! Jetzt hab ich nur noch das Problem das mir durch das tell und seek eine Zeile fehlt???!!!

          Sascha

          1. ist geändert! Jetzt hab ich nur noch das Problem das mir durch das tell und seek eine Zeile fehlt???!!!

            Ich weiß nicht warum du seek und tell brauchst.

            du liest Datei A ein und schreibst die Zeilen die du brauchst in B, da ist gar keine Notwendigkeit für seek oder tell - oder?

            Struppi.

            1. Ich weiß nicht warum du seek und tell brauchst.

              du liest Datei A ein und schreibst die Zeilen die du brauchst in B, da ist gar keine Notwendigkeit für seek oder tell - oder?

              Tja manchmal sieht man den Wald vor lauter Bäumen nicht!

              Jetzt klappt, war doch ganz einfach.-)

              Danke

  2. ich habe eine Text-Datei mit Mitgliederinformationen (feste Feldlängen).

    Bei der Größe solltest du dir dringend überlegen ob du nicht auf eine Datenbank wechseln willst.

    Nun habe ich ein kleines Perl proggi welches diese Datei einliest, unnötige Felder rauslöscht, Leerzeichen am Satzende entfernt, ein Semikolon als Trennzeichen einfügt und dann unter anderem Namen abspeichert.

    Nun hat sich die Eingangsdatei dramatisch vergrößert (Text-Datei hat etwa 930 MB, ca. 2.5 Mil. Zeilen).

    Es sollen nun mehrere Ausgangsdateien geschrieben werden, die erste z.B. von Mitglied 00000001 - 00100000, die nächste von 00100001 - 00200000 usw....

    Mein altes Proggi bringt meinen Rechner gnadenlos in den Speicherüberlauf.

    Naja, du musst die Datei ja nicht im ganzen einlesen, sondern jede Zeile einzeln bearbeiten und dann in eine Temporäre Datei schreiben und am Ende die alte löschen die Temporäre Datei umbennen.

    Danke für alle Tips!

    Eine richtige DB wäre wohl sinvoller.

    Struppi.

    1. 你好 Struppi,

      ich habe eine Text-Datei mit Mitgliederinformationen (feste Feldlängen).

      Bei der Größe solltest du dir dringend überlegen ob du nicht auf eine
      Datenbank wechseln willst.

      Die reine Datenmenge macht eine Datenbank nicht sinnvoller. Da muss man sich
      schon genauer anschauen, was fuer Daten das sind.

      再见,
       CK

      --
      Sich erinnern bedeutet, aus einer Erfahrung nicht ausreichend gelernt zu haben.
      http://wwwtech.de/
      1. Hi,

        Bei der Größe solltest du dir dringend überlegen ob du nicht auf eine
        Datenbank wechseln willst.

        Die reine Datenmenge macht eine Datenbank nicht sinnvoller. Da muss man sich
        schon genauer anschauen, was fuer Daten das sind.

        leider habe ich hier keine Wahl. Die Daten kommen auf CD-ROM und müssen dann als textfiles wieder auf eine Platte geschrieben werden. Mir wäre eine Datenbank auch lieber.

        Sascha

      2. Bei der Größe solltest du dir dringend überlegen ob du nicht auf eine
        Datenbank wechseln willst.

        Die reine Datenmenge macht eine Datenbank nicht sinnvoller. Da muss man sich
        schon genauer anschauen, was fuer Daten das sind.

        Das war ja gar nicht die Frage, er wollte damit ja was machen:
        'unnötige Felder rauslöschen' => "ALTER TABLE tabelle DROP Feld"
        'Leerzeichen entfernen' => UPDATE tabellenname set spaltenname= TRIM(spaltenname)
        Semikolon als trennzeichen => unötig

        Natürlich kannst du, wenn du Fit bist evtl. ein schnelleres System schreiben als jede DB, aber ich glaub in dem Fall wären das der falsche Ratschlag.

        Struppi.

        1. 你好 Struppi,

          Bei der Größe solltest du dir dringend überlegen ob du nicht auf eine
          Datenbank wechseln willst.

          Die reine Datenmenge macht eine Datenbank nicht sinnvoller. Da muss man
          sich schon genauer anschauen, was fuer Daten das sind.

          Das war ja gar nicht die Frage, [...]

          Klar ist das die Frage ;-) Du hast eine Datenbank empfohlen, obwohl du die
          Umstaende nicht kennst, das war ein bisschen vorschnell. Ob eine Datenbank
          sinnvoller ist, haengt von vielen Faktoren ab, u.a. vom Einsatzgebiet und
          den Daten.

          再见,
           CK

          --
          89,7% aller Statistiken sind frei erfunden!
          http://wwwtech.de/
          1. Bei der Größe solltest du dir dringend überlegen ob du nicht auf eine

            ^^^^^^^^^^

            Datenbank wechseln willst.

            Die reine Datenmenge macht eine Datenbank nicht sinnvoller. Da muss man
            sich schon genauer anschauen, was fuer Daten das sind.

            Das war ja gar nicht die Frage, [...]

            Klar ist das die Frage ;-) Du hast eine Datenbank empfohlen, obwohl du die

            ^^^^^^^^^^

            Umstaende nicht kennst, das war ein bisschen vorschnell. Ob eine Datenbank
            sinnvoller ist, haengt von vielen Faktoren ab, u.a. vom Einsatzgebiet und
            den Daten.

            Eben, weil ich die Umstände nicht kenne, hab ich im geraten zu überlegen ob ... und das hat er ja anscheinend auch schon. also war mein Ratschlag nicht vorschnell, sondern entsprach genau dem was Sascha ja auch gerne wollte wenn er könnte.

            Struppi.

  3. Hallo Sascha,

    little example:

    open(D1,"<D1");
    open(D2,">D2");

    while(<D1>) {
       <Zeile bearbeiten>;
       print D2 "... $_ ...\n"; # Zeile wegschreiben
    }

    Auf diese Weise läuft nix voll, so denke ich mal, weil jede Zeile direkt weggeschrieben wird. Wenn du natürlich die Datei mit @d=<@D1>; einliest, haut es dir den Speicher voll.

    Mfg,
    Jonny

    1. !!!

      @d=<D1>;

      !!!

      _sorry_

      Mfg,
      Jonny