Jutta Rosenbach: CGI: Daten in Datei schreiben, nicht am Ende sondern am ANFANG?

Hallo Ihr lieben Tüftlerinnen und Tüftler,

es geht um ein modifiziertes Simpchat-Skript. Mangels Scrollfreundlichkeit dieverser Browser möchte ich gerne, daß neue Beiträge nicht hinten angehängt, sondern immer am Anfang, also oben reingeschrieben werden.

Im SLFHTML wird bei selfhtml/tgcj.htm beschrieben, wie man eine datei öffnet und Daten am Schluß dazu schreibt.

Nun habe ich die Hoffnung, dass den CGI-Programmierern zuuufällig diesbezüglich ein praktischer Trick eingefallen ist, wie man Daten gleich vorne reinschreibt.

Bei Gästebüchern kann man ja wählen, ob die Einträge am Anfang oder am Schluß dazu sollen. Ich habe versucht, die Geschichte in das Script reinzubasteln. Aber es läuft nicht.

Über eine Antwort würde ich mich sehr freuen.

Gruß
Jutta

  1. Hallo Jutta,

    Nun habe ich die Hoffnung, dass den CGI-Programmierern zuuufällig diesbezüglich ein praktischer Trick eingefallen ist, wie man Daten gleich vorne reinschreibt.

    Dazu musst Du die vorhandene Datei erst mal in eine Liste einlesen. Dann erzeugst Du eine zweite Liste. Die ersten Elemente der neuen Liste belegst Du mit den neuen Zeilen vor, die am Anfang stehen sollen. Dann haengst Du die Zeilen der alten Liste an die neue an, z.B. in einer for-Schleife. Die neue Liste schreibst Du schliesslich komplett in die Datei (Datei dabei mit Modus "ueberschreiben" oeffnen).

    viele Gruesse
      Stefan Muenz

    1. Hallo Sefan

      Dazu musst Du die vorhandene Datei erst mal in eine Liste einlesen. Dann erzeugst Du eine zweite Liste. Die ersten Elemente der neuen Liste belegst Du mit den neuen Zeilen vor, die am Anfang stehen sollen. Dann haengst Du die Zeilen der alten Liste an die neue an, z.B. in einer for-Schleife. Die neue Liste schreibst Du schliesslich komplett in die Datei (Datei dabei mit Modus "ueberschreiben" oeffnen).

      Vielen Dank für Deine Antwort. Schade, daß es nicht einfacher geht.

      Viele Grüße
      Jutta

  2. hi!

    Im SELFHTML wird bei selfhtml/tgcj.htm beschrieben, wie man eine datei öffnet und Daten
    am Schluß dazu schreibt.

    Nun habe ich die Hoffnung, dass den CGI-Programmierern zuuufällig diesbezüglich ein
    praktischer Trick eingefallen ist, wie man Daten gleich vorne reinschreibt.

    Leider ist es wie bei allen mir bekannten Programmiersprachen so, dass man Daten immer nur an eine Datei anhängen kann, nicht an den Anfang oder eine andere Stelle setzen :-(

    Die erste Möglichkeit hat Stefan ja schon beschrieben: einfach alles in eine Liste einlesen. Du brauchst übrigens keine weitere Liste anlegen, sondern kannst ja gleich das neue in die Datei schreiben und dann wieder die erste Liste anhängen.
    Zweite Möglichkeit: falls du sowas mit ziemlich großen Dateien machen willst, ist es vielleicht weniger günstig, alles in eine Liste, möglicherweise sogar zwei Listen zu schreiben (wegen Speicherbedarf): du legst einfach eine temporäre Datei an und liest jeweils nur eine Zeile. Dauert vielleicht länger, spart aber Speicher.

    bye, Frank!

    1. hi Frank!

      Leider ist es wie bei allen mir bekannten Programmiersprachen so, dass man Daten immer nur an eine Datei anhängen kann, nicht an den Anfang oder eine andere Stelle setzen :-(

      Schade, ich hoffte es gäbe da auch so eine praktische simple Lösung, wie bei der Print-Geschichte.

      Die erste Möglichkeit hat Stefan ja schon beschrieben: einfach alles in eine Liste einlesen. Du brauchst übrigens keine weitere Liste anlegen, sondern kannst ja gleich das neue in die Datei schreiben und dann wieder die erste Liste anhängen.
      Zweite Möglichkeit: falls du sowas mit ziemlich großen Dateien machen willst, ist es vielleicht weniger günstig, alles in eine Liste, möglicherweise sogar zwei Listen zu schreiben (wegen Speicherbedarf): du legst einfach eine temporäre Datei an und liest jeweils nur eine Zeile. Dauert vielleicht länger, spart aber Speicher.

      Um große Dateien geht es nicht, nur um die messages.htm in einem Chat. Vielen Dank auch für Deine Ausführunge. Das Problem ist nur, daß ich aus Selfhtml weder Stefans noch Deine Ausführungen fortführen oder ableiten kann. Mir fehlt das Programmier-Verständnis.

      Ich lese "Liste einlesen" gehe in meine "Bibel", aber da ist im Beispiel die vollständige Liste schon im Beispiel-CGI definiert. Keine Ahnung, wie ich eine nicht definierte usw. usw.
      Jedenfalls weiß ich jetzt immerhin, es gibt keine simple Lösung. Dann müssen halt die MSI-Brausenden selbst hand anlegen und scrollen.

      Also vielen Dank nochmals

      Jutta

  3. Hallo Ihr lieben Tüftlerinnen und Tüftler,

    heute nacht wurde ich freundlicherweise nochmal im Chat ermutigt, nun doch auch die Skript-Passagen hinzustellen, da ich nicht weiß, wie ich die Hilfen von Stefan und Frank umsetzen kann.

    Der Chat besteht u.a. aus einer message.htm (in die dann die CGI's dynamisch was reinschreiben).  Nach jedem Refresch, also alle paar Sekunden müssen MSI-Nutzer sonst von Hand nach unten scrollen, wenn es nicht zu schaffen ist, neue Nachrichten immer oben erscheinen zu lassen.

    Das Skript, das fürs Einloggen und die normalen Nachrichten zuständig ist, enthält solche Sachen wie:

    read in the form data

    &get\_form\_data;  
    

    read in the old message file

    open (HTMLOLD, "$file");  
    @lines=<HTMLOLD>;  
    close(HTMLOLD);  
    
    open (NEW, ">$file");  
    print NEW "HIER ENSTEHT DER HTML-DATEI\_KOPF\n";  
    for ($i = 2; $i < 16; $i++)  
    {  
    

    print NEW "$lines[$i]";
    }
    print NEW "<b>$formdata{'username'}</B>";

    if ($formdata{'message'} eq "Betritt den Chat")  
    {  
    

    print NEW ": ";
      print NEW "<i>Betritt den Chat</i>";
    }
    else
    {
    print NEW ": ";
    print NEW ""$formdata{'message'}"";
    }
    print NEW "\n<p>\n";
    close(NEW);

    ########################################

    Add new Chatter

    open (CHATTER, ">>$chatfile");  
    print CHATTER " - $formdata{'username'}";  
    close (CHATTER);  
    

    ########################################

    initialize the message form after logon

    print "HIER WIRD DIE EINGABEMASKE ZUM CHATTEN GEBASTELT. DIE MAN BRAUCHT, NACHDEM MAN SICH ANGEMELDET HAT\n";  
    exit 0;  
    

    ########################################

    subs

    sub get_form_data {
    $buffer = "";
    read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
    @pairs=split(/&/,$buffer);
    foreach $pair (@pairs)
    {
      @a = split(/=/,$pair);
      $name=$a[0];
      $value=$a[1];
      $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
      $value =~ s/~!/ ~!/g;
      $value =~ s/+/ /g;
      # $value =~ s/</&lt;/g;  # html tag removal (optional)
      # $value =~ s/>/&gt;/g;  # html tag removal (optional)
      $value =~ s/\r//g;
      push (@data,$name);
      push (@data, $value);
    }
    %formdata=@data;
    %formdata;
    }

    Das Skript fürs Ausloggen sieht ähnlich aus.

    Über Hilfe würde ich mich sehr freuen
    Viele Grüße
    Jutta

    1. hi!

      Ich geh jetzt nur mal auf die entscheidende Stelle ein. Erstmal eine kurze Erklärung, was die einzelnen Stellen machen.

      open (HTMLOLD, "$file");

      Die Datei in der Variable $file wird zum Lesen geöffnet. Als Dateihandler dient der Name HTMLOLD. Die Datei dürfte die alte messages.html sein

      @lines=<HTMLOLD>;

      @lines ist ein Array bzw. eine Liste. In diese Liste werden alle Zeilen der eben geöffneten Datei eingelesen, also eine Zeile pro Listenwert.

      close(HTMLOLD);

      Die Datei wird wieder geschlossen.

      open (NEW, ">$file");

      Die gleiche Datei wird wieder geöffnet, dieses Mal aber mit dem Dateihandler NEW und zum Schreiben (erkennbar an dem ">"-Zeichen vor $file).

      print NEW "HIER ENSTEHT DER HTML-DATEI_KOPF\n";
      for ($i = 2; $i < 16; $i++)
      {

      »»   print NEW "$lines[$i]";

      }

      Diese for-Schleife bewirkt, das ab dem zweiten Listenwert einfach wieder alles bis zum 15. Listenwert in die Datei geschrieben wird.$lines[$i] ist der Zugriff auf das $i-te Element der Liste @lines.
      Was ich leider nicht ganz verstehe, ist, warum nur die ersten 15 Elemente der Liste wieder in die Datei geschrieben werden. Eigentlich sollten eher die letzten 15 Elemente reingeschrieben werden, oder seh ich da jetzt was falsch?

      print NEW "<b>$formdata{'username'}</B>";

      In eine neue Zeile wird der Benutzername des Absenders geschrieben.

      if ($formdata{'message'} eq "Betritt den Chat")
      {

      »»   print NEW ": ";
      »»   print NEW "<i>Betritt den Chat</i>";

      }

      Wenn jemand den Chat betritt, wird das geschrieben.

      else
      {

      »»   print NEW ": ";
      »»   print NEW ""$formdata{'message'}"";

      }

      Ansonsten wird die abgesendete Nachricht geschrieben.

      print NEW "\n<p>\n";
      close(NEW);

      Abschließend wird die Datei wieder geschlossen.

      Da das ganze oben ziemlich umständlich realisiert wurde, musst du einfach die Ausgaben in die Datei ein wenig vertauschen. Statt wie oben erst die Liste neu zu schreiben und dann die neue Nachricht, schreibst du erst die neue Nachricht und dann die Liste:

      print NEW "HIER ENSTEHT DER HTML-DATEI_KOPF\n";
      print NEW "<b>$formdata{'username'}</B>";

      if ($formdata{'message'} eq "Betritt den Chat")
      {
        print NEW ": ";
        print NEW "<i>Betritt den Chat</i>";
      }
      else
      {
        print NEW ": ";
        print NEW ""$formdata{'message'}"";
      }
      print NEW "\n<p>\n";

      for ($i = 2; $i < 16; $i++)
      {
           print NEW "$lines[$i]";
      }

      Das sollte eigentlich schon alles sein, falls ich nichts übersehen habe. Im übrigen muss ich sagen, dass einige Stellen wirklich etwas komisch, umständlich oder unnötig sind. Das Skript dient also nicht gerade als Musterbeispiel für Perl-Programmierung ;-))

      bye, Frank!

      1. Hallo Frank

        vielen Dank, für Deine ausführliche Beschreibung.
        Wenn ich könnte, würde ich Dich jetzt am liebsten zu einem virtuellen Bierchen einladen.

        Jedes Wort war wichtig, denn so konnte ich gleich all die zusätzlichen kleinen Schwierigkeiten mit bereinigen.

        Viele Grüße
        Jutta