Martin: Probleme beim schreiben von Daten in eine Datei.

hi folks,

ich habe probleme mit einem kleinen perl program das formulardaten in eine datei schreiben soll. leider kommen die daten nicht in der datei an. vermutlich ist der zurückgeliferte hash leer. bin noch newbie in perl, ich wäre extremultradankbar wenn jemand eine idee hat warum folgende zeilen nicht funktionieren. thx:-)

PROG:
#!c:/perl/perl.exe -w
read (STDIN, $daten, $ENV{'CONTENT_LENGTH'});
%daten = &CGIDA ($daten);
$name = "test".".dat";
$verz = "[lw]:\[verzeichnis]\[subverz]\[subverz]\[subverz]\";
open DATEN, ">>$verz$name";
while ( ($temp, $wert) = each %daten)
   {
    print "$wert";
    $temp = 0
   }
close DATEN;
sub CGIDA
{
    local ($cgiskalar, $name, $daten);
    local @cgiliste;
    local %cgihash;
    if ($_[0])
    {
        $cgiskalar = $_[0];
    }
    else
    {
        print STDERR "keine Daten uebergeben!!!\n";
    }
    @cgiliste = split(/[&;]/ , $cgiskalar);
    foreach $listeneintrag (@cgiliste)
    {
        ($name, $daten) = split( /=/ , $listeneintrag);
        $name =~ s/%(..)/pack("c",hex($1))/ge;
        $daten =~ s/%(..)/pack("c",hex($1))/ge;
        $cgihash {$name} = $daten;
    }
    return $cgihash
}
print "Content-type: text/html\n\n";
print '<html>';
print '<head>';
print '<title>Antwortseite</title>';
print '</head>';
print '<body>';
print '<hr>';
print '<h1>Ihre Daten wurden erfolgreich gespeichert!<H1>';
print '<hr>';
print '</body>';
print '</html>';

PROGENDE
bemerkung: hab oben nur die richtigen verz gegen dummies ersetzt aber die pfade sind definitiv ok.

hoffe jemand kann mir helfen,thx.
cu martin

  1. Hallo Martin

    ich habe probleme mit einem kleinen perl program das formulardaten in eine datei schreiben soll. leider kommen die daten nicht in der datei an. vermutlich ist der zurückgeliferte hash leer.

    read (STDIN, $daten, $ENV{'CONTENT_LENGTH'});

    So kriegt das Script die Daten, wenn es via POST-Methode aufgerufen wurde (im Formular: <form .... method="post">
    Falls die GET-Methode benutzt wird (<form method="get"> oder Direktübergabe von Daten in der URL hinter Fragezeichen), dann musst du notieren:

    $daten = $ENV{'QUERY_STRING'};

    Zur Kontrolle kannst du ja mal unten, wo die print-Befehle stehen, notieren:
    print '$daten\n';

    Dann siehst du, ob Daten eingelesen wurden.

    viele Gruesse
      Stefan Muenz

    1. print '$daten\n';

      Sinniger ist hier:

      print "$daten\n";

      noch besser ist es natürlich, CGI.pm zu nutzen - wie bereits empfohlen.

      Peter

      1. Hallo Peter

        Sinniger ist hier:
        print "$daten\n";

        Stimmt ;-)

        noch besser ist es natürlich, CGI.pm zu nutzen - wie bereits empfohlen.

        Halbwahre Dinge soll man so oft wiederholen, bis auch der letzte Depp sie fuer wahr haelt, gelle?
        Ich will damit sagen: es gibt die CGI.pm, sie hat ihren Sinn und Zweck, aber hoert bitte auf, hier jeden zu "belehren". Man kann auch so wie Martin es tut Daten zuverlaessig einlesen. Und waehrend die CGI.pm in zwei Jahren wieder "out" sein wird, weil es dann eine viel tollere .pm dafuer geben wird, wird Martins Script immer noch laufen.

        viele Gruesse
          Stefan Muenz

        1. Halbwahre Dinge soll man so oft wiederholen, bis auch der letzte Depp sie fuer wahr haelt, gelle?

          Unsinn.

          Ich will damit sagen: es gibt die CGI.pm, sie hat ihren Sinn und Zweck, aber hoert bitte auf, hier jeden zu "belehren". Man kann auch so wie Martin es tut Daten zuverlaessig einlesen. Und waehrend die CGI.pm in zwei Jahren wieder "out" sein wird, weil es dann eine viel tollere .pm dafuer geben wird, wird Martins Script immer noch laufen.

          CGI.pm ist ein Standardmodul: daran wird sich auch nichts aendern. Ein Skript, dass dieses Modul nutzt funktioniert mit allen jetzen und auch den zukuenftigen Perldistributionen.

          Der Code dagegen, der hier propagiert wird, funktioniert nicht in allen Fällen.

          Peter

          1. Halbwahre Dinge soll man so oft wiederholen, bis auch der letzte Depp sie fuer wahr haelt, gelle?

            Unsinn.

            Ich will damit sagen: es gibt die CGI.pm, sie hat ihren Sinn und Zweck, aber hoert bitte auf, hier jeden zu "belehren". Man kann auch so wie Martin es tut Daten zuverlaessig einlesen. Und waehrend die CGI.pm in zwei Jahren wieder "out" sein wird, weil es dann eine viel tollere .pm dafuer geben wird, wird Martins Script immer noch laufen.

            CGI.pm ist ein Standardmodul: daran wird sich auch nichts aendern. Ein Skript, dass dieses Modul nutzt funktioniert mit allen jetzen und auch den zukuenftigen Perldistributionen.

            Der Code dagegen, der hier propagiert wird, funktioniert nicht in allen Fällen.

            Peter

            hallo peter,
            danke fuer deine hilfe, leider bin ich wie gesagt noch newbie auf dem weg zum perlprogrammierer. wie ich in einem thread von gestern schon einmal geschildert habe versuche ich perl in seinen grundzügen zu erlernen, weil ich der meinung bin das man ohne verstanden zu haben was man tut, nichts von allein macht, sondern nur auf die dinge von anderen zurück greift. sicherlich werde ich in zukunft auch module einbinden (wenn ich so weit bin) weil sie mit sicherheit zu produktiveren ergebnissen führen. bis jetzt weiss ich allerdings so viel das es bibliotheken und module gibt! zur anwendung bin ich noch nicht gekommen.

            danke nochmals für die hilfe
            cu martin

          2. Hallo Peter

            CGI.pm ist ein Standardmodul: daran wird sich auch nichts aendern. Ein Skript, dass dieses Modul nutzt funktioniert mit allen jetzen und auch den zukuenftigen Perldistributionen.

            Vor zwei Jahren war es die cgi-lib.pl, heute die CGI.pm, morgen die universal-data.pm oder wie auch immer. Kann sein, dass eine Aufnahme in die Standardbibliothek ein "Ewigkeitsrecht" impliziert. Aber Moden kommen und gehen. Es wird halt jedes Jahr was anderes "empfohlen". Wieso hat Martin eigentlich bislang niemand empfohlen, alles mit PHP zu machen? Das ist doch eh viel besser als Perl und ist derzeit heiss in Mode.
            Tut mir leid, wenn ich da etwas "zynisch" bin - ich bin zwar noch kein EDV-Veteran, aber selbst ich hab schon genug kommen und gehen sehen. Und damit keine Missverstaendnisse aufkommen: in http://www.teamone.de/selfaktuell/artikel/formmail.htm verwende ich die CGI.pm selber ;-)

            viele Gruesse
              Stefan Muenz

            1. Hallo Stefan und Ihr alle,

              also hier wird gerade so schön diskutiert ;-)

              Tut mir leid, wenn ich da etwas "zynisch" bin - ich bin zwar noch kein EDV-Veteran, aber selbst ich hab schon genug kommen und gehen sehen. Und damit keine Missverstaendnisse aufkommen: in http://www.teamone.de/selfaktuell/artikel/formmail.htm verwende ich die CGI.pm selber ;-)

              hmm, also wenn Du hier anstelle des CGI.pm das web.pm http://cgi.xwolf.com/web/index.shtml verwenden tätest, könntest Du wie gehabt die Eingaben elegant parsen:

              %in = &ReadParse;

              und auch eine etwaige eingegebene eMail-Absender-Adresse auf Syntax prüfen:

              $val = isMail($absender);

              print MAIL "From: $absender\n";

              Das Letztere fehlt in Deinem Script, sorry, aber wie soll ein Empfänger sonst auf "Reply" klicken können?

              Viele Grüße, Rolf

              1. Hallo Rolf,

                hmm, also wenn Du hier anstelle des CGI.pm das web.pm http://cgi.xwolf.com/web/index.shtml verwenden tätest, könntest Du wie gehabt die Eingaben elegant parsen:

                Danke, du bestaetigst mich aufs Wunderbarste ;-)
                Aber auch danke fuer den Tip!

                viele Gruesse
                  Stefan Muenz

            2. Tut mir leid, wenn ich da etwas "zynisch" bin - ich bin zwar noch kein EDV-Veteran, aber selbst ich hab schon genug kommen und gehen

              Du bist nicht zynisch, sondern verstehst den Kern der Sache nicht. Das was hier angepriesen wird, funktioniert einfach nicht 100%ig - im Gegensatz zu CGI.pm.

              »»  sehen. Und damit keine Missverstaendnisse aufkommen: in http://www.teamone.de/selfaktuell/artikel/formmail.htm verwende ich die CGI.pm selber ;-)

              Aha, warum?

              Peter

        2. Ich will damit sagen: es gibt die CGI.pm, sie hat ihren Sinn und Zweck, aber hoert bitte auf, hier jeden zu "belehren". Man kann auch so wie Martin es tut Daten zuverlaessig einlesen. Und waehrend die CGI.pm in zwei Jahren wieder "out" sein wird, weil es dann eine viel tollere .pm dafuer geben wird, wird Martins Script immer noch laufen.

          viele Gruesse
            Stefan Muenz

          THX,
          von dieser seite hab ich das zwar nich gesehen, aber ist ein vernünftiges argument! lol

          auf diesem weg moechte ich auch noch DANKE sagen weil ich ohne SelfHTML niemals nich (*g) zur webentwicklung gekommen wäre.

          ps hab das problem übrigens grade gelöst:
          ein return $cgihash (macht keinen Sinn!!!)
          aber return %cgihash (funzt prima)

          Danke nochmals an alle für die freundliche unterstützung.

          cu martin

  2. Hi Martin!

    Mach Dir das Leben nicht so schwer und nimm CGI.pm (use CGI qw(:standard)). Dann greifst Du auf die Formulardaten über $var_name   =  param('name') zu, wobei 'name' der Name des Formularfeldes ist. Das Modul nimmt Dir auch die Abfrage der Methode (post oder get) ab.

    Gruß Frank

  3. read (STDIN, $daten, $ENV{'CONTENT_LENGTH'});
    %daten = &CGIDA ($daten);

    Dass Du das besser sein laesst und dafuer param aus dem Modul CGI.pm benutzt, wurde dir bereits geraten. Ansonsten:

    use CGI::Carp 'fatalsToBrowser';

    und

    open DATEN, ">>$verz$name";

    open DATEN ">>$verz$name" or die "$verz$name: $!";

    Peter

  4. ich nochmal,
    danke für eure antworten, hab das problem teilweise schon gelöst.
    zuerst wurde gar nix in die Datei geschrieben. Lag wohl daran das man beim print befehl auch noch den dateihandle übergeben sollte!!!!!
    tja nun schreibt er mir in die datei aber leider nicht den inhalt aus variable "$wert"??????????

    übrigens den tip mit den modulen hab ich schon oft gehört. ich werds mit den modulen auch versuchen, aber erstmal probier ich perl in seinen grundsätzen zu verstehen.

    hier nochmals der geaenderte code wenn jemand weiss warum $wert nix übergibt please tell me! thx 2 all:

    PROG:
    #!c:/perl/perl.exe -w
    read (STDIN, $daten, $ENV{'CONTENT_LENGTH'});
    %daten = &CGIDA ($daten);
    $name = "test".".dat";
    $verz = "c:\inetpub\intranet\test\data\";
    open (DATEN, ">>$verz$name");
    while ( ($temp, $wert) = each %daten)
       {
        print DATEN ("$wert");
        $temp = 0
       }
    print DATEN ("<br>");
    close DATEN;
    sub CGIDA
    {
        local ($cgiskalar, $name, $daten);
        local @cgiliste;
        local %cgihash;
        if ($_[0])
        {
            $cgiskalar = $_[0];
        }
        else
        {
            print STDERR "keine Daten uebergeben!!!\n";
        }
        @cgiliste = split(/[&;]/ , $cgiskalar);
        foreach $listeneintrag (@cgiliste)
        {
            ($name, $daten) = split( /=/ , $listeneintrag);
            $name =~ s/%(..)/pack("c",hex($1))/ge;
            $daten =~ s/%(..)/pack("c",hex($1))/ge;
            $cgihash {$name} = $daten;
        }
        return $cgihash
    }
    print "Content-type: text/html\n\n";
    print '<html>';
    print '<head>';
    print '<title>Antwortseite</title>';
    print '</head>';
    print '<body>';
    print '<hr>';
    print '<h1>Ihre Daten wurden erfolgreich gespeichert!<H1>';
    print '<hr>';
    print '</body>';
    print '</html>';

    PROGENDE

    cu martin

    1. Hi,

      übrigens den tip mit den modulen hab ich schon oft gehört. ich werds mit den modulen auch versuchen, aber erstmal probier ich perl in seinen grundsätzen zu verstehen.

      Sinn der Module ist es, Dir das Leben *einfacher* zu machen.

      Gerade wenn Du anfängst, die ersten Skripte lauffähig zu bekommen, sollest Du für Standardaufgaben fertige Standardlösungen verwenden.
      CGI.pm ist hierbei eine der naheliegendsten Hilfen - und seine Verwendung erspart Dir, die CGI-Schnittstelle schon jetzt bis ins Detail verstehen zu müssen.

      Ich an Deiner Stelle würde also Perl *mit* Modulen lernen.
      Sobald Du fit bist - und Zeit genug hast -, kannst Du immer noch den Quelltext von CGI.pm lesen und dann ggf. eine für Deine Belange optimierte Sparversion selbst herstellen.
      Bis dahin kommst Du mit den Modulen schneller - und mit mehr Erfolgserlebnissen - ans Ziel.

      mfG - Michael
      (der Perl auch zuerst ohne Module gelernt hat und im Laufe der Zeit immer mehr eigenen Code wegwirft und durch Modulaufrufe ersetzt ;-)

      1. Hi,

        übrigens den tip mit den modulen hab ich schon oft gehört. ich werds mit den modulen auch versuchen, aber erstmal probier ich perl in seinen grundsätzen zu verstehen.

        Sinn der Module ist es, Dir das Leben *einfacher* zu machen.

        Gerade wenn Du anfängst, die ersten Skripte lauffähig zu bekommen, sollest Du für Standardaufgaben fertige Standardlösungen verwenden.
        CGI.pm ist hierbei eine der naheliegendsten Hilfen - und seine Verwendung erspart Dir, die CGI-Schnittstelle schon jetzt bis ins Detail verstehen zu müssen.

        Ich an Deiner Stelle würde also Perl *mit* Modulen lernen.
        Sobald Du fit bist - und Zeit genug hast -, kannst Du immer noch den Quelltext von CGI.pm lesen und dann ggf. eine für Deine Belange optimierte Sparversion selbst herstellen.
        Bis dahin kommst Du mit den Modulen schneller - und mit mehr Erfolgserlebnissen - ans Ziel.

        mfG - Michael
        (der Perl auch zuerst ohne Module gelernt hat und im Laufe der Zeit immer mehr eigenen Code wegwirft und durch Modulaufrufe ersetzt ;-)

        hallo michael,

        ich weiss ja das mir die module das leben erleichtern, aber wenn ich den code der hinter den modulen steckt nicht versteh, kann ich sie egeintlich auch nicht anwenden (weil ich ja auch nicht VERSTEH was das modul für mich macht!!!) klar ist der effekt und das erfolgserlebniss grösser (ausser das ich die fehler aus diesem thread selbst behoben hab, was ein riesiges erfolgserlebnis für mich war.(und das SM auf einen meiner threads antwotrtet!!!*g)) als wenn man stundenlang vor dem code sitzt weil man in zeile 245635 ein komplzierte subroutine geschrieben hat (und ein semikolon darin vergessen*g). mich würde interressieren ob du denkst das sich das lernen ohne module heute fuer dich ausgezahlt hat? ich glaube der umstand das du ohne die module gelernt hast hatte mehr effekt als wenn dir jemand sagt du musst modul x nehmen und variable y und dann funzt es und du hast 2000 zeilen gespart.(NUR VERSTANDEN HAB ICHS NICHT!!!)

        dank auf jedenfall für deine unterstützung, und ich hoffe das ich auch bald von mir behaupten kann meine routine gegen die besseren module ersetzt zu haben.

        cu martin

    2. Hi Martin!

      übrigens den tip mit den modulen hab ich schon oft gehört. ich werds mit den
      modulen auch versuchen, aber erstmal probier ich perl in seinen grundsätzen zu verstehen.

      Nichts dagegen zu sagen, kannst Dir aber trotzdem mal http://www.oreilly.de/catalog/perlmodger/ ansehen. Unter 'manpages' findest Du u.a. CGI.pm.

      Gruß Frank

  5. Hallo Martin,

    Nachdem Du die bereits gemachte Vorschläge berücksichtigt hast, versuch ich mich mal in einer Fehlersuche, damit auch ein Lerneffekt eintritt.

    [...]

    %daten = &CGIDA ($daten);

    Hier erwartest Du eine Hash als Rückgabewert (komme später darauf zurück ;-)).

    $name = "test".".dat";

    ^.....(1)
    Die Maskierungen(1) ist hier überflüssig. In Strings musst Du nur Sonderzeichen maskieren, die in einer mit "" eingefassten Zeichenkette eine Sonderbedeutung haben ($@% als Variablenkennzeichner " als Stringterminator,\ als Escaper )
    Du kannst also ruhig $name = "test.dat" schreiben.

    [...]

    open DATEN, ">>$verz$name";
    while ( ($temp, $wert) = each %daten)
       {
        print "$wert";

    ^.....(2)

    $temp = 0

    ^.....fehlendes Semikolon (testest Du eigentlich Dein Skripts mit perl -cw skript.pl ?)

    }
    close DATEN;

    Wenn Du in die geöffnete Datei schreiben willst, musst Du auch der print-Anweisung(2) mitteilen worein sie schreiben soll. Im Moment schreibst Du auf <STDOUT>. Gib bei (2) DATEN als Dateihandle an und schon landen die Daten eben dort.
    Zudem musst Du Variablen nicht in Anführungszeichen setzen, wenn Du sie ausgeben willst, da das nur "Zeit kostet" (macht sich wahrscheinlich bei so kleinen Skripts nicht sonderlich bemerkbar). Perl muss nämlich erst den String parsen um die Variable durch eine Wert zu ersetzen (wenn ich mich nicht täusche, und das im Forum aufgeschnappte Wissen ausreichend ist ;-)

    sub CGIDA {

    [...]

    local %cgihash;

    ^......(3)

    Imho ist 'my' das was Du hier (3) brauchst, um eine Variable lokal zu machen ;-)
    [...]

    return $cgihash
    }          ^...(4) ^.....fehlendes Semikolon

    Du übergibst einen leeren Skalar (4), und nicht den/dem/das Hash, den Du erstellt hast (siehe oben).

    [...]

    hoffe jemand kann mir helfen,thx.

    Hoffentlich hilft Dir das weiter. Aber in Zukunft solltest Du Deine Skripte erst mal vom Perl-Interpreter checken lassen:
       perl -cw myskript.pl
    damit hättest Du schon mal Fehlermeldungen erhalten, die Dich auf wichtige Stellen stoßen.
    Außerdem ist use strict; auch nicht schlecht, da es bei Ungereimtheiten mit Variablen eine Meldung ausstößt. Das erfordert allerdings das explizite Deklarieren von Variablem mit 'my'.

    Gruß AlexBausW

    P.S.: Ich hoffe keinen größeren Fehler übersehen zu haben. Die logischen Fehler bzw. die Ablaufsteuerung musst Du selbst noch mal durchdenken.

    1. Hallo Martin,

      Nachdem Du die bereits gemachte Vorschläge berücksichtigt hast, versuch ich mich mal in einer Fehlersuche, damit auch ein Lerneffekt eintritt.

      [...]

      %daten = &CGIDA ($daten);
      Hier erwartest Du eine Hash als Rückgabewert (komme später darauf zurück ;-)).

      $name = "test".".dat";
                         ^.....(1)
      Die Maskierungen(1) ist hier überflüssig. In Strings musst Du nur Sonderzeichen maskieren, die in einer mit "" eingefassten Zeichenkette eine Sonderbedeutung haben ($@% als Variablenkennzeichner " als Stringterminator,\ als Escaper )
      Du kannst also ruhig $name = "test.dat" schreiben.

      [...]

      open DATEN, ">>$verz$name";
      while ( ($temp, $wert) = each %daten)
         {
          print "$wert";
                  ^.....(2)

      $temp = 0
                      ^.....fehlendes Semikolon (testest Du eigentlich Dein Skripts mit perl -cw skript.pl ?)
         }
      close DATEN;

      Wenn Du in die geöffnete Datei schreiben willst, musst Du auch der print-Anweisung(2) mitteilen worein sie schreiben soll. Im Moment schreibst Du auf <STDOUT>. Gib bei (2) DATEN als Dateihandle an und schon landen die Daten eben dort.
      Zudem musst Du Variablen nicht in Anführungszeichen setzen, wenn Du sie ausgeben willst, da das nur "Zeit kostet" (macht sich wahrscheinlich bei so kleinen Skripts nicht sonderlich bemerkbar). Perl muss nämlich erst den String parsen um die Variable durch eine Wert zu ersetzen (wenn ich mich nicht täusche, und das im Forum aufgeschnappte Wissen ausreichend ist ;-)

      sub CGIDA {
      [...]
          local %cgihash;
             ^......(3)

      Imho ist 'my' das was Du hier (3) brauchst, um eine Variable lokal zu machen ;-)
      [...]

      return $cgihash
      }          ^...(4) ^.....fehlendes Semikolon

      Du übergibst einen leeren Skalar (4), und nicht den/dem/das Hash, den Du erstellt hast (siehe oben).

      [...]

      hoffe jemand kann mir helfen,thx.

      Hoffentlich hilft Dir das weiter. Aber in Zukunft solltest Du Deine Skripte erst mal vom Perl-Interpreter checken lassen:
         perl -cw myskript.pl
      damit hättest Du schon mal Fehlermeldungen erhalten, die Dich auf wichtige Stellen stoßen.
      Außerdem ist use strict; auch nicht schlecht, da es bei Ungereimtheiten mit Variablen eine Meldung ausstößt. Das erfordert allerdings das explizite Deklarieren von Variablem mit 'my'.

      Gruß AlexBausW

      P.S.: Ich hoffe keinen größeren Fehler übersehen zu haben. Die logischen Fehler bzw. die Ablaufsteuerung musst Du selbst noch mal durchdenken.

      hallo alex,

      das ist schon das 2mal das ich auf deine herrvoragende hilfe zählen kann, (diesmal war chetah auch nicht schneller *g*)

      um deinen lerneffekt zu bestätigen see my post above ich den fehler mit dem hash und dem datenhandle gefunden.
      trotzallem danke für die vielen kleinen versteckten fehler die perl nichts auszumachen scheinen. (prog läuft jetzt mit korrektem ergebnis..)
      übrigens rufe ich perl mit -w auf muss gleich mal nachschauen was -c macht.

      danke für die tips,
      cu martin

      1. Hi,

        trotzallem danke für die vielen kleinen versteckten fehler die perl nichts auszumachen scheinen.

        es ist *Deine* Entscheidung, ob sie Perl etwas "ausmachen" sollen.
        Je mehr Prüfungen Du einschaltest ("use strict" und "perl -w" würde ich beim Entwickeln *immer* verwenden), desto genauer prüft Perl Dein Programm, bevor es selbiges ausführt.

        mfG - Michael