Gary: csv - Dateihandhabung

Hallo zusammen

Habe mal ein paar allgemeine Fragen zur Handhabung von csv-Dateien:

Ich hatte mal für einen Kollegen ein Programm geschrieben, daß Ihm erlaubte seine Kunden zu erfassen und auf einen Blick zu sehen, welche Verträge ein Kunde hat und wie die weiteren  Daten sind. Das hatte ich damals über Access gelöst, mit entsprechenden Abfragemöglichkeiten. Knackpunkt war, daß ich ihm 10 Felder vordefiniert hatte (in einer eigens entworfenen Maske).

Hatte ein Kunde nun mehr als 10 Verträge (Selten aber möglich), gabs Probleme.

Ich überlege gerade, wie man es realisieren kann, in einer DB (mit csv-Datei), Werte dazwischen zu schieben:

----------------------------
A1;
   <--A2 einschieben!
B1;
C1;
----------------------------

Gibt es eine andere Möglichkeit A2 einzuschieben, außer die gesammte DB einzulesen, den entsprechenden Schreibvorgang nach A1 abzuwarten und mit A2 zu ergänzen, um dannach den Rest ebenfalls wieder zurück zu schreiben?

Mir fällt keine andere ein. :-(

Das Problem, daß Daten erwarte, deren Menge ich noch nicht kenne müssen doch auch schon andere gehabt haben. Man kann ja schlecht hunderte von Variablen "reservieren", in der Hoffnung, sie vielleicht doch mal zu gebrauchen.

Gruß Gary

  1. Moin!

    Du solltest mal unter "Datennormalisierung" nachsehen.

    Du hast Kunden, die haben z.B. Adresse, meinetwegen Geburtstag und sogar eine Kundennummer (ID).
    Du hast Verträge die gehören zu einem Kunde.
    Du hast Rechnungen, die gehören zu einem Vertrag der zu einem Kunde gehört.
    Du hast Zahlungen, die gehören je zu einer Rechnung, die zu je einem Vertrag gehören, die zu je einem Kunden gehören.

    MFFG (Mit freundlich- friedfertigem Grinsen)

    fastix

    1. Moin auch

      Im Access gib es einen absolut einzigartigen Schlüssel für jeden Datensatz, weil-> Meier und Schneider gibts wie Sand am Meer. Dieser Schlüssel verhindert Verwechslungen. Sinngemäß nimmt man als solch einen Identifizierer die Kundennummer.

      Das von dir hier:
      Du hast Kunden, die haben z.B. Adresse, meinetwegen Geburtstag und sogar eine Kundennummer (ID).
      Du hast Verträge die gehören zu einem Kunde.
      Du hast Rechnungen, die gehören zu einem Vertrag der zu einem Kunde gehört.
      Du hast Zahlungen, die gehören je zu einer Rechnung, die zu je einem Vertrag gehören, die zu je einem Kunden gehören.

      ist alles richtig. Aber dannach kommt ja der nächste Datensatz. Und wenn sich beim vorhergehenden Datensatz was ändert (ein weiterer Vertrag kommt hinzu) muß ich da ja eine Lücke oder Platz schafen. Das war eigentlich die Frage, ob dies nur über kommplettes auslesen und neu einschreiben funktioniert? Oder kann man im Perl den "Datenzeiger direkt an eine gewünschte Stelle schieben und dort platz machen?

      Alternativ könnte man auch mit Ordnern schaffen, aber da wird das auslesen wieder komplizierter...

      1. Moin!

        ist alles richtig. Aber dannach kommt ja der nächste Datensatz. Und wenn sich beim vorhergehenden Datensatz was ändert (ein weiterer Vertrag kommt hinzu) muß ich da ja eine Lücke oder Platz schafen.

        Nein.

        1. Du benutzt eine Tabelle Kunden. Diese enthält die Daten des Kunden.
        2. Du benutzt eine Tabelle Verträge. Diese enthält die Verträge und als ein Merkmal die eindeutige Kundennummer.

        Du willst wissen, welche Verträge der Kunde mit der Kundennummer "K0815" hat?

        Du gehst die Datensätze in der Tabelle Verträge durch und listest alle Verträge die in der Spalte Kundennummer "K0815" stehen haben.

        So ist deren Anzahl jedenfalls nicht von vornherein begrenzt.

        Kundennummer; Name; Vorname; Adresse  
        K0815;Meier;Franz;Mustergasse 17, 12345 Musterstadt  
        K0816;Jäger;Franz;Eisenweg 1;45789 Safershausen  
          
        Verträge:  
        ID;Typ;Kunde;Beginn;Ende  
        1;2;K0815;1.1.2000;31.12.2005  
        2;1;K0816;1.1.2001;31.12.2006  
        3;2;K0815;1.1.2006;  
        4;1;K0815;1.1.2006;  
          
        Vertragstypen:  
        ID;Name  
        1;Lebensversicherung  
        2;KFZ-Haftpflicht  
          
        Der Franzl aus Musterstadt hat(te) 3 Verträge:  
          
        Eine am 31.12.2006 beendete KFZ-Haftpflicht vom 01.01.2000. (Vertragsnummer 1)  
        Eine am 01.01.2006 begonnene KFZ-Haftpflicht.               (Vertragsnummer 2)  
        Eine am 01.01.2006 begonnene Lebensversicherung.            (Vertragsnummer 4)
        

        fastix

        1. Hi fastfix

          1. Du benutzt eine Tabelle Kunden. Diese enthält die Daten des Kunden.
          2. Du benutzt eine Tabelle Verträge. Diese enthält die Verträge und als ein Merkmal die eindeutige Kundennummer.

          Raffiniert! Echt clever!!!

          Das hat auch noch den Vorteil, daß die Datei "Verträge" die einzelnen Datensätze nicht mal der Reihe nach beinhalten muss. Da ja beim Auslesen nach der KdNr vorgegangen wird!

          Beim Einstellen neuer Verträge ist deine Struktur gut.
          Beim Auslesen der Bestände ebenfalls.

          Aber was mache ich, wenn ich einen Datensatz aus der Kategorie "Vertäge" löschen möchte?

          Da muss ich dann zwangsläufig die ganzen Verträge auslesen, bis die Stelle kommt mit dem zu löschenden Datensatz, den ich dann nicht zurückschreibe...

          Oder geht es besser?

          Merci nochmal

          Gary

          PS. Hab dein Post ausgedruckt ;-) ich hoffe du hast nichts dagegen...

          1. Moin!

            Da muss ich dann zwangsläufig die ganzen Verträge auslesen, bis die Stelle kommt mit dem zu löschenden Datensatz, den ich dann nicht zurückschreibe...

            Oder geht es besser?

            Ja. Folge dem Vorschlag von Vinzenz Mai und lerne ein wenig SQL. Perl kann z.B. prima mit MySQL / SQLite umgehen.

            Für das Tabellendesign gilt das Gesagte natürlich weiter.

            MFFG (Mit freundlich- friedfertigem Grinsen)

            fastix

            1. Hi fastfix und alle anderen

              Ja. Folge dem Vorschlag von Vinzenz Mai und lerne ein wenig SQL. Perl kann z.B. prima mit MySQL / SQLite umgehen.

              Danke an alle. Habe die letzten Stunden mal ein bischen in MySQL in Verbindung mit perl gestöbert. Ganz schön harter Tabak. Sehr gut beschrieben ist der Einstieg hier. Trozdem ist es für einen MySQL-Einsteiger schwierig die Handhabung zu lernen. Das geht nicht von Heute auf Morgen.

              DBI-Modul plus Treiber DBD. Datenbank einrichten / Verbinden (conect) schreiben, lesen, trennen usw...

              Die Fehlerquellen, die ich mir damit schaffe sind nicht zu vernachlässigen. Hinzu kommt, daß man eventuelle Fehler, die bei den einzelnen Prozessen auftreten können, alle separat abfangen muß --> die.

              Da scheint es, zumindest aus meiner noch beschrännkten Sichtweise, einfacher, übersichtlicher und praxisnäher zu sein, mit mehreren csv-Dateien zu arbeiten. Ganz nach fastfix-Prinzip.

              Ich habe auch noch keinen wirklichen Vorteil der Schnittstelle zu MySQL begriffen. Für mich sieht es subjektiv eher komplizierter aus. Außerdem nutze ich dann wieder Code und Strukturen, die ich A->nicht begreife und B->
              aus fremder Feder stammen. Somit habe ich bei der csv-Lösung eher das Gefühl, die Kontrolle über das was ich mache zu haben...

              Mit freundlichem Gruß

              Gary

              PS.: Es ist halt wie immer bei Computersprachen: Je mehr man sich damit beschäftigt, desto mehr Türen öffnen sich... und der Raum dahinter ist immer noch ein bischen größer, als der Raum davor, in dem man stand!

              --

              Gästebuch in Not - braucht dringend noch ein zwei Einträge... funktioniert übrigens auch mit einer csv-Datei :-)
              1. Moin!

                Ich habe auch noch keinen wirklichen Vorteil der Schnittstelle zu MySQL begriffen.

                Mach es  einfach mal. Wenn Du dann begriffen hast, dass es jeweils nur wenige Zeilen für

                • den Zugriff (connect) auf die Datenbank
                • die Abfrage
                • die Auswertung der Rückgaben

                braucht und dass sich insbesondere der Connect in ein zu inkludierendes Skript auslagern lässt und Du dann nur noch die Punkte Formulierung der Abfrage (Löschen/Update) und Auswertung der Rückfrage zu leisten hast dann wirst Du nach einigen Gehversuchen mit MySQL (oder einer anderen Datenbank/einem anderen DBMS) merken, dass dies echt "endgeil" ist. Das ganze CSV-Geraschel wirst Du dann bestenfalls noch via DBD:CSV machen wollen, was Matti Maekitalo dir vorgeschlagen hatte.

                Mein Beispiel z.B. wäre mit einem

                SELECT  
                `Vertraege`.`Beginn`  
                `Vertraege`.`Ende`  
                `Vertragstypen`.`Name`  
                  
                FROM `Kunden`, `Vertraege`, `Vertragstypen`  
                  
                WHERE  
                   `Kunden`.`Vorname`='Franz'  
                    AND `Kunden`.`Ort` LIKE '%Musterstadt%'  
                    AND `Vertraege`.`Kunde`= `Kunden`.`Kundennummer`  
                    AND `Vertragstypen`.`ID`= `Vertraege`.`Typ`  
                  
                ORDER BY  `Vertraege`.`Beginn`;
                

                erledigt, welches in einen String gepackt der Datenbank "vor den Kopf geknallt" wird:

                $table_data = $dbh->prepare($sql);  
                $table_data->execute;
                

                und in einem hübsch auszulesenden Objekt resultiert. Das ist doch leicht.

                Ein Vertrag ist beendet?

                Einfach

                UPDATE VertraegeSETEnde= '2010-08-11' WHERE Vertraege.Id=1 AND Kunde='K0815' LIMIT 1;

                in einen String packen und der Datenbank "vor den Kopf knallen", also schon wieder:

                $table_data = $dbh->prepare($sql);  
                $table_data->execute;
                

                Auswerten ob die abgefassten Zeilen in Ihrer Anzahl der Erwartung entsprechen. Bingo!

                Ich finde: Einfacher geht es kaum, vor allem wenn ich das mit dem Theater mit dem CSV-Dateien vergleiche, welches vor allem dann auftritt, wenn ich jetzt noch auf DBD::CSV verzichte... und alles vom Öffnen, dem Packen in Arrays, der Auswertung, dem Bauen eines neuen Arrays, dem Zurückschreiben vergleiche. Die Fehlerquellen, die Du Dir damit schaffst sind erst recht nicht zu vernachlässigen. Vielleicht hast Du genau das bisher getan: Prüfst Du denn überhaupt, ob Deine Datei

                1. vorhanden ist?
                2. schreibbar ist?
                3. überhaupt die erwartete Zahl an Spalten?
                4. geschweige denn die erwarteten Datentypen enthält?
                5. ob Du den richtigen Datentyp in die Spalte x schreibst?
                6. erfolgreich geschrieben wurde?

                Kümmerst Du Dich um locks?

                Dagegen ist die Verwindung einer Datenbank echt einfach.

                fastix

                1. Abend fastix

                  SELECT

                  Vertraege.Beginn
                  Vertraege.Ende
                  Vertragstypen.Name

                  FROM Kunden, Vertraege, Vertragstypen

                  WHERE
                     Kunden.Vorname='Franz'
                      AND Kunden.Ort LIKE '%Musterstadt%'
                      AND Vertraege.Kunde= Kunden.Kundennummer
                      AND Vertragstypen.ID= Vertraege.Typ

                  ORDER BY  Vertraege.Beginn;

                  
                  >   
                  > erledigt, welches in einen String gepackt der Datenbank "vor den Kopf geknallt" wird:  
                  > ~~~perl
                  
                  $table_data = $dbh->prepare($sql);  
                  
                  > $table_data->execute;
                  
                  

                  und in einem hübsch auszulesenden Objekt resultiert. Das ist doch leicht.

                  Ein Vertrag ist beendet?

                  Einfach

                  UPDATE VertraegeSETEnde= '2010-08-11' WHERE Vertraege.Id=1 AND Kunde='K0815' LIMIT 1;

                  in einen String packen und der Datenbank "vor den Kopf knallen", also schon wieder:

                  $table_data = $dbh->prepare($sql);

                  $table_data->execute;

                  
                  >   
                  >   
                  >  Auswerten ob die abgefassten Zeilen in Ihrer Anzahl der Erwartung entsprechen. Bingo!  
                    
                  OK, 1:0 für dich, vorausgesetzt man kann damit umgehen. Das Abfragen, Rein- und Rausschreiben scheint wirklich einfacher, wenn man die Eingangshürde erstmal genommen hat. :-)  
                    
                  
                  >   
                  > [...] Prüfst Du denn überhaupt, ob Deine Datei  
                  >   
                  > 1. vorhanden ist?  
                  
                  Nein...  
                    
                  
                  > 2. schreibbar ist?  
                  
                  Nein...  
                    
                  
                  > 3. überhaupt die erwartete Zahl an Spalten?  
                  
                  Nein...  
                    
                  
                  > 4. geschweige denn die erwarteten Datentypen enthält?  
                  
                  Nein... nix Typen -> alles String! Ist Perl Wurst ob Zahl oder Buchstabe!  
                    
                  
                  > 5. ob Du den richtigen Datentyp in die Spalte x schreibst?  
                  
                  Nein...  
                    
                  
                  > 6. erfolgreich geschrieben wurde?  
                  
                  Nein...  
                    
                  
                  > Kümmerst Du Dich um locks?  
                  
                  Ja... Ich glaube Exclusive ist die sicherste Variante  
                    
                  
                  >   
                  > [Dagegen ist die Verwindung einer Datenbank echt einfach.](http://oreilly.com/catalog/msql/chapter/ch10.html)  
                  
                  Die Seite ist nun gebookmarked für später - Die besagten langen Wintertage ;-)  
                    
                    
                  [Hier](http://www.wc-report.info/test/GBM.txt) siehst du mein \_erstes\_ eigenes Gästebuch in Perl!  
                  Viele Anfängerfehler:  
                    
                  1)  
                  Viel goto verwendet->Wird zukünftig nur noch mit Übersichtlichen Sprungmarken realisiert und mit eindeutigen Zurücksprung bzw. Endsprüngen.  
                    
                  2)  
                  Ich öffne und schliesse mehrmals die Gästebuchdatei. Weil es anders mit den Funktionen nicht geht.  
                    
                  3)  
                  Was mich wirklich an Perl stört: mit "my" und "$"-Zeichen deklarierte Variabeln scheinen nicht über das gesamte Script hinweg zu funktionieren. Oft muß ich die Funktion für die aktuelle Zeit und das Datum mehrmals im Code notieren, weil Perl scheinbar weiter unten die Variabeln vergißt. Bei der IP- Abfrage dasselbe. Wenn ich den Wert brauche muss ich "$ENV {'REMOTE\_ADDR'}" direkt verwenden, auch wenn ich weiter obenals Beispiel "my $RemoIp = $ENV {'REMOTE\_ADDR'}" schreibe, weiss das Programm weiter unten wieder nicht was §RemoIp ist...  
                    
                  Scheint Perl hat ein Alzheimer - Problem...  
                    
                  Aber - großes aber: Es funktioniert. Mein ach so schlechtes Programm funktioniert. Da darf ich mich ein wenig freuen...  
                    
                  Gruß + Gute Nacht  
                    
                  Gary  
                    
                  PS.: Die Umlaute sind im .pl-Datei korrekt. Nur hir für Demozwecke ist das Script als .txt-Datei gehostet... da stimmen halt die Umlaute nicht. Ist aber jetzt hier egal...
                  
                  1. Viele Anfängerfehler:

                    Viel goto verwendet->Wird zukünftig nur noch mit Übersichtlichen Sprungmarken realisiert und mit eindeutigen Zurücksprung bzw. Endsprüngen.

                    Verwende Funktionen, das ist übersichtlich.

                    Ich öffne und schliesse mehrmals die Gästebuchdatei. Weil es anders mit den Funktionen nicht geht.

                    Damit sind deine flocks überflüssig, dass hatte ich dir aber bereits erklärt.

                    Was mich wirklich an Perl stört: mit "my" und "$"-Zeichen deklarierte Variabeln scheinen nicht über das gesamte Script hinweg zu funktionieren.

                    Ja, das wird z.b. hier alles erklrärt http://aktuell.de.selfhtml.org/artikel/cgiperl/scoping/

                    Struppi.

                    1. Hi Struppi :-)

                      Verwende Funktionen, das ist übersichtlich.

                      Habe das gerade in deinem Link gesehen. mit B(); usw...
                      Werde ich auf jeden Fall genauer studieren!

                      Ich öffne und schliesse mehrmals die Gästebuchdatei. Weil es anders mit den Funktionen nicht geht.

                      Damit sind deine flocks überflüssig, dass hatte ich dir aber bereits erklärt.

                      Nein, während sie offen ist, ist die Datei für andere gesperrt. Ist sie zu, kann ja ein anderer Prozess die datei nutzen. Das erste Perlprog wartet dann eben bis das zweite Perlprog ferti ist. Kein Problem.

                      Es gibt bei mir zwei Scripte:

                      GuestBookManager->
                      Der vergleicht den letzen eintrag mit dem neusten, und schreibt die Daten, wenn sie korrekt sin ein.

                      GuestBookReader-> Der liest nur die Einträge aus und stellt sie online.

                      Alle beide nutzen die guest.csv-Datei je im ex-Modus. Bisher keine Probleme gehabt!

                      Ja, das wird z.b. hier alles erklrärt http://aktuell.de.selfhtml.org/artikel/cgiperl/scoping/

                      Gut, erklärt ist wohl zuviel gesagt. Ich finde sehr abstrakt. Also was ich davon geistig mitgenommen habe:

                      ---------------------------------------------------------------------------
                      my->
                      erzeugt eine Variable, die nur innerhalb einer Funktion ihre Gültigkeit hat.
                      ---------------------------------------------------------------------------
                      local->
                      erzeugt eine Variable, die im ganzen Script ihre Gültigkeit hat.
                      ---------------------------------------------------------------------------

                      Jetzt kommt der schwierige Teil: Hatte local $Var vorher einen Wert (Bsp.A), und wird dieser Wert durch einen anderen neuen ersetzt (Bsp. B), steht zunächst der neue Wert (B)in der local $Var. Wir der neue Wert gebraucht oder ausgelesen, steht dann wieder der alte Wert (A) drin? Oder wie ist das mit dem Beispiel gemeint. Ist es tatsächlich so, wäre das Schwachsinn. Denn _ich_ weise einen Wert in die Variable und der hat solange dort zu bleiben, bis _ich_ ihn durch was auch immer ersetze!

                      Ganz allgemein zu dieser Variable-Erklärungs-Seite:

                      Ich kann mich dem Vorschlag stehts "my" zu verwenden, nicht anschließen. Es mühselig, Variabeln immer neu zu füllen, bzw. gefährlich, in einem Script zwei gleichnamige my deklarierte Variabeln zu verwenden, im Vertrauen darauf, das diese sich eh nicht tangieren, da lokal auf Ihre Funktion begrenzt sind.

                      Ich bin der Meinung, daß Jede Variable nur einmal vorkommen darf (Verwechslungsgefahr). Und zumindest ich bin von früher daran gewohn, an jeder Stelle des Programms zuverlässig auf den Inhalt einer Variable zugreifen zu können.

                      Gruß Gary

                        Ich öffne und schliesse mehrmals die Gästebuchdatei. Weil es anders mit den Funktionen nicht geht.

                        Damit sind deine flocks überflüssig, dass hatte ich dir aber bereits erklärt.

                        Nein, während sie offen ist, ist die Datei für andere gesperrt. Ist sie zu, kann ja ein anderer Prozess die datei nutzen. Das erste Perlprog wartet dann eben bis das zweite Perlprog ferti ist. Kein Problem.

                        Nein, da du in deinem skript mehrere Dateioperationen einbauen willst, wird jedesmal wenn du die Datei schliesst der flock aufgehoben und ein anderer Prozess kann die Datei manipulieren, such mal nach "race condition"

                        Es gibt bei mir zwei Scripte:

                        GuestBookManager->
                        Der vergleicht den letzen eintrag mit dem neusten, und schreibt die Daten, wenn sie korrekt sin ein.

                        Und liest die Datei vorher ein, nachdem sie geschlossen wurde, bevor sie geschrieben werden, kann ein anderer Prozess diese Datei lesen und wird die Änderungen des ersten Skripts überschreiben. Und das wird passieren, das weiß ich, weil meine ersten Skripte auch so arbeiteten. x-mal waren die Daten weg.

                        Wenn das Skript Daten ändern soll, musst du die Datei während des ganzen Prozess, also bei einlesen und schreiben locken.

                        Alle beide nutzen die guest.csv-Datei je im ex-Modus. Bisher keine Probleme gehabt!

                        *ironie* Das ist natürlich ein Argument

                        ---------------------------------------------------------------------------

                        my->
                        erzeugt eine Variable, die nur innerhalb einer Funktion ihre Gültigkeit hat.

                        Nein, innerhalb eines Blocks.

                        ---------------------------------------------------------------------------

                        local->
                        erzeugt eine Variable, die im ganzen Script ihre Gültigkeit hat.

                        Nein. es erzeugt eine lokale Kopie. Aber local sollte nicht mehr verwendet werden, steht auch im Artikel.

                        Ganz allgemein zu dieser Variable-Erklärungs-Seite:

                        Ich kann mich dem Vorschlag stehts "my" zu verwenden, nicht anschließen.

                        Komisch warum machen das dann alle so?
                        Vielleicht hilft dir dieser Artikel http://wiki.perl-community.de/Wissensbasis/UseStrict

                        Struppi.

                        1. Hi Struppi

                          Und liest die Datei vorher ein, nachdem sie geschlossen wurde, bevor sie geschrieben werden, kann ein anderer Prozess diese Datei lesen und wird die Änderungen des ersten Skripts überschreiben. Und das wird passieren, das weiß ich, weil meine ersten Skripte auch so arbeiteten. x-mal waren die Daten weg.

                          Das ist weniger erfreulich *g* Gut beim Gästebuch wäre das jetzt auch kein Beinbruch. Bei einer Datenbank mit Kundendaten, die mühevoll zusammengetragen wurden, schon eher.

                          ---------------------------------------------------------------------------

                          my->
                          erzeugt eine Variable, die nur innerhalb einer Funktion ihre Gültigkeit hat.

                          Nein, innerhalb eines Blocks.

                          Gut dann innerhalb eines Blocks, aber immerhin nicht im ganzen Programm - das habe ich verstanden.

                          ---------------------------------------------------------------------------

                          local->
                          erzeugt eine Variable, die im ganzen Script ihre Gültigkeit hat.

                          Nein. es erzeugt eine lokale Kopie. Aber local sollte nicht mehr verwendet werden, steht auch im Artikel.

                          Lokale Kopie? Komm du willst mich fertig machen! *lol* Was soll denn das jetzt mit der Kopie? Ich denke wir sprechen über Variabeln?

                          Ist jetzt eine mit local erzeugte oder definierte oder von mir aus auch kopierte Variable im ganzen Perlprogramm verfügbar oder nicht?

                          Ich will mein C64 zurück! Oder den Amiga 500 nehm ich auch gerne...

                          Ich kann mich dem Vorschlag stehts "my" zu verwenden, nicht anschließen.

                          Komisch warum machen das dann alle so?

                          Vielleicht schreiben die gerne mehr Code als erforderlich? *fleißig?*
                          Oder noch besser - einen Spruch den ich hier im Forum vor Jahren mal aufgeschnappt habe:
                          1 Mio. Fliegen können nicht irren - Scheiße schmeckt toll!

                          Vielleicht hilft dir dieser Artikel http://wiki.perl-community.de/Wissensbasis/UseStrict

                          Habe ihn durchgelesen. Kann mich aber für die Gefangennahme der Variablen in einem Block nicht begeistern - "free the tiny variables"...

                          Finde es besser, daß man sich einen Variabel-Stamm zulegt, und den überall verwenden kann. Auch sollte eine Variable nur einmal vorkommen...

                          ->was solls - bin halt Altmodisch!

                          Grüsse Gary

                          PS.: Race-Conditions trifft natürlich nur zu, wenn mehrere Prozesse (so wie in meinem Gästebuch) stattfinden könnten. Ein DB-Programm, das aber nur auf einem Rechner läuft und nur von einer Person genutzt wird, bracht sich aber darüber keine Gedanken zu machen. Wenn man bei der Programmierung sauber gearbeitet hat.

                          1. Vielleicht hilft dir dieser Artikel http://wiki.perl-community.de/Wissensbasis/UseStrict
                            Habe ihn durchgelesen. Kann mich aber für die Gefangennahme der Variablen in einem Block nicht begeistern - "free the tiny variables"...

                            Deine Freiheit ist vergleichbar mit einem Kind, das du absichtlich auf die Strasse stellst, damit es jeder überfahren kann.

                            mfg Beat

                            --
                            ><o(((°>           ><o(((°>
                               <°)))o><                     ><o(((°>o
                            Der Valigator leibt diese Fische
                            1. Hi Beat

                              Habe ihn durchgelesen. Kann mich aber für die Gefangennahme der Variablen in einem Block nicht begeistern - "free the tiny variables"...

                              Deine Freiheit ist vergleichbar mit einem Kind, das du absichtlich auf die Strasse stellst, damit es jeder überfahren kann.

                              Du meintest - damit Sie vom  Schulbus abgeholt werden, oder vom Taxi, oder von Mama, oder Oma oder... - eben der, der sie gerade benötigt!

                              Apropos überfahren... Das ist dann wieder ein "Umfeldproblem" -> sprich liegt am Programmierer! ;-)

                              Gruß Gary

                              1. Moin!

                                Apropos überfahren... Das ist dann wieder ein "Umfeldproblem" -> sprich liegt am Programmierer! ;-)

                                Nein, nein. Das mit den Variablen macht schon Sinn.

                                Wichtig: Ich nehme in folgenden Beispiel KEINERLEI RÜCKSICHT auf Syntax oder Sprache - der Code sollte nirgendwo benutzt werden.

                                Stell Dir vor, Du schreibst ein Programm. Du schreibst es so, dass es den Wert einer Ware in Euro berechnet. Dieses verwendet (unklug) die Variable 'u' für irgendetwas:

                                $u='100 Stück Butter kosten ';  
                                $wert = 100;
                                

                                jetzt kommt aber einer und will den Wert in USD haben.

                                Also schreibt einer eine Funktion, die den Kurs holt und den Wert umrechnet:

                                function eur2usd ($betrag) {  
                                    $u=getKurs('EUR', 'USD'); // dies sei eine weitere Funktion;  
                                    return ($betrag*$u).'$';  
                                }
                                

                                Jetzt kann diese Funktion in einem weiteren Skript sein, welches mit use oder (in PHP) include eingebunden wird.

                                Steht jetzt irgendwo in Deinem Programm:

                                $wert=eur2usd($wert);  
                                print $u.$wert;
                                

                                Dann bekommst Du, so lange Deine Variablen nicht "frei" also nicht "global" sind, wie erwartet:

                                "100 Stück Butter kosten 129.38$"

                                Sind Deine Variablen aber global (Du nennst es frei), dann bekommst Du

                                "1.29129.38$" als Ausgabe.

                                Grund ist der, dass der Programmierer des 2. Skriptes nicht weiß, welche Variablen Du verwendet hast. Deshalb ist es eine gute Idee, wenn er den gesamten Namensraum selbst nutzen kann, so langer nicht im main() herumschreibt. Auch derjenige, der das Hauptskript schreibt, kann sich darauf verlassen, dass durch Funktionen Dritter seine Variablen nicht zerstört oder überladen werden.

                                Ergo macht es Sinn, Variablen nur lokal gültig sein zu lassen.

                                MFFG (Mit freundlich- friedfertigem Grinsen)

                                fastix

                                1. Morgen fastix :-)

                                  Jetzt kann diese Funktion in einem weiteren Skript sein, welches mit use oder (in PHP) include eingebunden wird.

                                  Moment:
                                  Entgegengesetzt meiner bisherigen Meinung, das use xyz externe Perlmodule verwendet ist es also möglich selber ein Script zu erstellen und dies mit use EigenesScript; einzubinden? Ahhhhaaaaaa! - jetzt wird mir einiges klarer!

                                  Das entpräche in etwa dem alten "chain"-Befehl in Basic, welches dem laufendem Programm erlaubte, aus einer externen Datei weiteren Programmcode anzuhängen/ zuzuladen.

                                  Nur aus neugier:
                                  Ich habe ja schon
                                  -------------------------------
                                  use Fcntl ':flock';
                                  use CGI -no_xhtml;
                                  use CGI::Carp qw(fatalsToBrowser warningsToBrowser);
                                  -------------------------------
                                  eingebunden und verwendet.

                                  Dann nehme ich z. B. an das dieses flock:
                                  -------------------------------
                                  flock(LASTCONTROL, LOCK_EX);
                                  -------------------------------
                                  in verbindung steht mit dem:
                                  -------------------------------
                                  use Fcntl ':flock';
                                  -------------------------------

                                  Wie hat man sich den Austausch von Variabeln, Rechnungen und Routinen zwischen dem aktiven Perlprogramm und dem über ein "use" eingebundenes Script vorzustellen?

                                  Wenn es geht bitte in einfachen Worten *g*

                                  Gruß Gary

                                  PS.: Werde für das neue Projekt DBD::CSV; verwenden

                                  1. Bounjoun Gary,

                                    Moment:
                                    Entgegengesetzt meiner bisherigen Meinung, das use xyz externe Perlmodule verwendet ist es also möglich selber ein Script zu erstellen und dies mit use EigenesScript; einzubinden? Ahhhhaaaaaa! - jetzt wird mir einiges klarer!

                                    Was meintest Du unter extern? Ein Modul ist immer ein externes Programm, da es ja nicht bestandteil des Skripts ist. Du kannst nur Module einbinden, die Teil Deiner Perl-Distribution sind, oder selbst geschriebene, jedenfalls nur solche, die in @INC enthalten sind.

                                    Natürlich kannst Du zusätzliche Module, die Du neu benötigst, nachträglich installieren - oder auf einem fremden Server ohne Shell-Zugriff durch den Provider _installieren lassen_. Viele Module lassen sich aber einfach in ein Verzeichnis kopieren (z.B. Unterverzeichnis von cgi-bin).

                                    Ein Perlprogramm besteht aus vielerlei. Von simplen print-Anweisungen zur Ausgabe und ein paar Kontrollstrukturen, wie Du sie derzeit hast, über Unterprogrammen (oder: eigene Funktionen, in Perl Subroutinen genannt). Programmteile zur Wiederverwendung werden in Libraries oder eben Modulen ausgelagert, und stehen somit zur Verfügung für alle Skripte, die diese Programmteile brauchen.

                                    Adiou.

                                  2. Moment:
                                    Entgegengesetzt meiner bisherigen Meinung, ....

                                    Du solltest dir dringend - ganz dringend!!! - die Dokumentation von Perl durchlesen. Dir entgeht vieles.

                                    Das entpräche in etwa dem alten "chain"-Befehl in Basic, welches dem laufendem Programm erlaubte, aus einer externen Datei weiteren Programmcode anzuhängen/ zuzuladen.

                                    Nein, use lädt ein Modul in der Übersetzungsphase. Was du meinst klingt nach require

                                    Dann nehme ich z. B. an das dieses flock:

                                    flock(LASTCONTROL, LOCK_EX);

                                    in verbindung steht mit dem:

                                    use Fcntl ':flock';

                                    Wie hat man sich den Austausch von Variabeln, Rechnungen und Routinen zwischen dem aktiven Perlprogramm und dem über ein "use" eingebundenes Script vorzustellen?

                                    Lies die Doku

                                    Wenn es geht bitte in einfachen Worten *g*

                                    Vieles ist nicht einfach, also auch nicht einfach zu erklären. Du kannst natürlich versuchen eine nicht so umfangreiche Doku zu verwenden (z.b. die von selfhtml), aber damit entgehen dir immer noch viele Sachen, die du mit Perl machen kannst.

                                    Struppi.

                          2. local->
                            erzeugt eine Variable, die im ganzen Script ihre Gültigkeit hat.

                            Nein. es erzeugt eine lokale Kopie. Aber local sollte nicht mehr verwendet werden, steht auch im Artikel.

                            Lokale Kopie? Komm du willst mich fertig machen! *lol* Was soll denn das jetzt mit der Kopie? Ich denke wir sprechen über Variabeln?

                            Es wird in dem lokalen Block eine Kopie der Variabel angelegt und ausserhalb ist wieder die ursprüngliche vorhanden.

                            Ist jetzt eine mit local erzeugte oder definierte oder von mir aus auch kopierte Variable im ganzen Perlprogramm verfügbar oder nicht?

                            Wenn du vorher eine globale Variabel definiert hast, ja.

                            Ich will mein C64 zurück! Oder den Amiga 500 nehm ich auch gerne...

                            Das sieht man deinem Programm an. aber ich empfand damals schon eine Erweiterung für den C64 sehr Klasse, mit der man Funktional programmieren konnte (ich weiß aber nicht mehr wie das hieß - ich glaube es war aus der C'64er)

                            globale/lokale Variabeln sind eine riesige Erleichteurng für jeden, es ist absolut der Horror sich für jede Variabel einen neuen Namen zu überlegen, wenn das Programm eine gewisse Größe überschreitet.

                            Und use strict hilft enorm beim programmieren. Tippfehler bei Variabeln wie $lenght statt $length findest du sofort und nicht erst, wenn zufällig die Funktion aufgerufen wurde.

                            Ich kann mich dem Vorschlag stehts "my" zu verwenden, nicht anschließen.

                            Komisch warum machen das dann alle so?
                            Vielleicht schreiben die gerne mehr Code als erforderlich? *fleißig?*
                            Oder noch besser - einen Spruch den ich hier im Forum vor Jahren mal aufgeschnappt habe:
                            1 Mio. Fliegen können nicht irren - Scheiße schmeckt toll!

                            Nein, weil sie faul sind und ihre Zeit nicht mit der Fehlersuche verplempern wollen.

                            Finde es besser, daß man sich einen Variabel-Stamm zulegt, und den überall verwenden kann. Auch sollte eine Variable nur einmal vorkommen...

                            Das ist vielleicht bei deinem Gästebuch im jetzigen Stadium noch sinnvoll, aber irgendwann wird dieser Wunsch ein Alptraumszenarium, wenn du die 10 Variabel die z.b. eine Länge oder Höhe bezeichnet, benötigst.

                            PS.: Race-Conditions trifft natürlich nur zu, wenn mehrere Prozesse (so wie in meinem Gästebuch) stattfinden könnten. Ein DB-Programm, das aber nur auf einem Rechner läuft und nur von einer Person genutzt wird, bracht sich aber darüber keine Gedanken zu machen. Wenn man bei der Programmierung sauber gearbeitet hat.

                            Ob man es nicht braucht ist eine andere Frage, es ist aber vermutlich nicht so wichtig wie bei der CGI Programmierung und genau darüber sprechen wir hier, oder?

                            Struppi.

          2. Moin!

            Aber was mache ich, wenn ich einen Datensatz aus der Kategorie "Vertäge" löschen möchte?

            Nichts da mit Löschen! "Nächste Woche" will Dein Kunde wissen, welche Verträge seine Kunden hatten. Markiere ihn mit beendet, z.B. dadurch, dass in der Spalte "beendet" ein Datum steht (bitte in optimal lesbarer/berechenbarer/vergleicharer/sortierbarer Form z.B. 2010-31_03T00:00:00) welches kleiner als der Abfragezeitpunkt ist.

            Mit Datenbanken und SQL ist das kinderleicht zu machen. Lerne also SQL und optimal gleich die Nutzung von Datenbankmanagementsystemen wie MySQL oder PostgreSQL.

            MFFG (Mit freundlich- friedfertigem Grinsen)

            fastix

            1. Tach auch.

              Mit Datenbanken und SQL ist das kinderleicht zu machen. Lerne also SQL und optimal gleich die Nutzung von Datenbankmanagementsystemen wie MySQL oder PostgreSQL.

              Oder DBD::CSV, um bei CSV zu bleiben und trotzdem die perl-DB-Schnittstelle nutzen zu können.

              Bis die Tage,
              Matti

              1. Moin!

                Oder DBD::CSV, um bei CSV zu bleiben und trotzdem die perl-DB-Schnittstelle nutzen zu können.

                Ja. Stimmt. Ich vergaß wie geil Perl sein kann. Da kann man tatsächlich mit (einfachen) SQL-Befehlen auf CSV-Dateien schießen.

                MFFG (Mit freundlich- friedfertigem Grinsen)

                fastix

                1. Morgen allerseits!

                  Oder DBD::CSV, um bei CSV zu bleiben und trotzdem die perl-DB-Schnittstelle nutzen zu können.

                  Ja. Stimmt. Ich vergaß wie geil Perl sein kann. Da kann man tatsächlich mit (einfachen) SQL-Befehlen auf CSV-Dateien schießen.

                  Heist das etwa, daß man die weiter unten von fastix erwähnten Abfragen über die DBD machen kann und die Schnittstelle kümmert sich um die CSV-Datei (einlesen,auslesen,schreiben)?

                  Nur noch mal zur Bestätigung...

                  Gruß Gary

                  1. Moin!

                    Heist das etwa, daß man die weiter unten von fastix erwähnten Abfragen über die DBD machen kann und die Schnittstelle kümmert sich um die CSV-Datei (einlesen,auslesen,schreiben)?

                    Nur noch mal zur Bestätigung...

                    Ja.

                    MFFG (Mit freundlich- friedfertigem Grinsen)

                    fastix

                    1. Hi

                      Heist das etwa, daß man die weiter unten von fastix erwähnten Abfragen über die DBD machen kann und die Schnittstelle kümmert sich um die CSV-Datei (einlesen,auslesen,schreiben)?

                      Nur noch mal zur Bestätigung...

                      Ja.

                      Geil!

                      Gruß Gary

  2. Hallo Gary,

    Habe mal ein paar allgemeine Fragen zur Handhabung von csv-Dateien:
    Ich überlege gerade, wie man es realisieren kann, in einer DB (mit csv-Datei), Werte dazwischen zu schieben:

    Datenbankmanagementsystem (DBMS) verwenden und CSV-Dateien entsorgen. Kann gern auch was dateibasiertes wie SQLite sein. Es ist keine besonders gute Idee, die Funktionalität von Hand zu Fuß zu erstellen, die Dir ein DBMS schon fertig liefert.

    Freundliche Grüße

    Vinzenz

    1. Hi Vinzenz

      Datenbankmanagementsystem (DBMS) verwenden und CSV-Dateien entsorgen. Kann gern auch was dateibasiertes wie SQLite sein. Es ist keine besonders gute Idee, die Funktionalität von Hand zu Fuß zu erstellen, die Dir ein DBMS schon fertig liefert.

      Ja das hat was!

      Im Access war das damals recht schnell umgesetzt. Nun habe ich aber schon länger kein Windows mehr. Wenn ich mich für ein solches Programm breitschlagen lasse, sollte es aber auf nem Windows-Rechner genauso laufen wie auf meiner Ubuntu-Linux-Maschine. Da lag ein Perlscript nahe. Eventuell auch mit der Option dies auf einem Server laufen zu lassen, so hätten alle Mitarbeiter ständig zugriff auf die aktuellen Daten, da alle zentral deponiert wären. Jaja ich weis -  die Sicherheit der Daten in einem solchen Fall müssten dann noch mal gesondert behandelt werden.

      Gibt es etwas in Richtung Access, das sowohl auf Linux und auf Windows läuft?

      Oder Alternativ direkt über das Internet - einen Browser hat (fast) jedes OS.
      Damit wäre das Kompatibilitätsproblem beiseite geräumt.

      PS1.: Ich weis, das mein Serververmieter MYSQL drauf hat! *g*

      PS2.: Ich habe keinen Schimmer von MySQL...

  3. Ich überlege gerade, wie man es realisieren kann, in einer DB (mit csv-Datei), Werte dazwischen zu schieben:


    A1;
       <--A2 einschieben!
    B1;
    C1;

    Bitte sprich in den Begriffen Fields und Records.
    Willst du ein Field einschieben oder einen Record einschieben?

    Gibt es eine andere Möglichkeit A2 einzuschieben, außer die gesammte DB einzulesen, den entsprechenden Schreibvorgang nach A1 abzuwarten und mit A2 zu ergänzen, um dannach den Rest ebenfalls wieder zurück zu schreiben?

    Mit Tie:File wird nicht die gesamte Datei eingelesen.

    Falls du Felder brauchst, deren Wert ein Array ist, brauchst du einfach einen Drittes Datensatztrennzeichen:
    Recordseparator
    Fieldseparator
    ArrayelementSeperator

    Plus natürlich die entsprechenden maskierungen demaskierungen bei lesen/schreiben

    Mir fällt keine andere ein. :-(

    Du kannst Daten auch mittels dem Modul Storable als Perl-Hash speichern.
    Das ist allerdings für wachsende Daten nicht geeignet, da immer der ganze Hash eingelesen wird.

    Du kannst dir auch ein anderes Konzept überlegen.
    Querystrings sind ein mögliches Format um Daten zu speichern. Felder dürfen mehrmalig vorkommen, und die Feldnamen werden ja auch gespeichert.

    Das eignet sich vor allem für Daten, die ausser iherm Id-Feld beliebig viele und vor allem optionale Felder haben.

    mfg Beat

    --
    ><o(((°>           ><o(((°>
       <°)))o><                     ><o(((°>o
    Der Valigator leibt diese Fische
  4. hi,

    Gibt es eine andere Möglichkeit A2 einzuschieben, außer die gesammte DB einzulesen, den entsprechenden Schreibvorgang nach A1 abzuwarten und mit A2 zu ergänzen, um dannach den Rest ebenfalls wieder zurück zu schreiben?

    Wenn Du das transaktionsicher haben willst, nein. Transaktion heißt: Lesen UND Schreiben, und das darf nur ein Prozess. Schau Dir flock() an und sysopen(). Die Funktion sysopen() ist etwas komfortabler als open() was Dateizugriffe betrifft. Es empfiehlt sich, die Datei auf einen Hash oder ein Array zu lesen und es lohnt auf jeden Fall, sich damit zu befassen.

    Das sieht dann so aus:

      
    tie %hash, 'myClass', 'dateiname'; # LOCK_EX  
    # in Class/Konstruktor wird das Handle mit sysopen() erstellt und gelockt  
    # die Datei wird deserialisiert auf einen hash gelesen  
      
    {code...}  
      
    untie %hash; # Serialize, zurückschreiben der Datenstruktur in die Datei  
    
    

    Freilich sind CSV-Dateien u.a. Dateien, die textlich strukturiert sind nicht gerade performant. Mit pack() und unpack() kannst Du jedoch Felder definieren und damit auf einen Delimiter verzichten:

      
     $binary_rec = pack("Z10Z10", $name, $vname); # Zwei Felder, je 9 byte  
     ($name, $vname) = unpack("Z10Z10", binary_rec); # binary_rec hat 10 byte  
    
    

    Geschrieben und gelesen wird im binmode HANDLE (:raw), zum Lesen gibts die read()-Funktion. Zeilenumbrüche braucht eine solche Datei nicht. Performant sind solche Dateien bis einige Megabyte und mehr 20000 Records.

    Hotti

    1. hi,

      $binary_rec = pack("Z10Z10", $name, $vname); # Zwei Felder, je 9 byte
      ($name, $vname) = unpack("Z10Z10", binary_rec); # binary_rec hat 10 byte

        
      Ne, sind 20 byte, sorry, Druckfehler ;-)  
        
      Schablone "Z" füllt binäre Nullen auf, wobei das letzte byte auch für eine NULL reserviert ist, wichtig. Mit "Z10" ist die verfügbare Feldlänge also 9 byte. Im obigen Beispiel wird ein Record mit der read()-Funktion gelesen wie folgt:  
        
      ~~~perl
        
      binmode HANDLE; # important!  
      while( read(HANDLE, $bin, 20)){  
         ($name, $vname) = unpack("Z10Z10", $bin);  
      }  
      
      

      Die "Platzverschwendung" erfolgt nur in der Datei, nicht im RAM, da liegen exact die Werte ohne angehängte Nullen. Für UTF-8-codierte Zeichen bitte entsprechend Platz reservieren.

      Wenn Du es ganz ganz sicher haben willst, das Lesen und Schreiben, lege eine Checksumme am Anfang oder Ende der Datei an. Wenn es nur die Länge ist, genügen 4 byte als checksum (Schablone "N"). Md5-hex-checksummen brauchen 32 byte (256 bit) hier kann außer der Länge noch diese oder jene Angabe in die checksumme gewurstet werden, je nach Bedarf ;-)

      Hotti

      1. Hi hotti

        das...

        $binary_rec = pack("Z10Z10", $name, $vname); # Zwei Felder, je 9 byte
        ($name, $vname) = unpack("Z10Z10", binary_rec); # binary_rec hat 10 byte

        
        >   
        > Ne, sind 20 byte, sorry, Druckfehler ;-)  
        >   
        > Schablone "Z" füllt binäre Nullen auf, wobei das letzte byte auch für eine NULL reserviert ist, wichtig. Mit "Z10" ist die verfügbare Feldlänge also 9 byte. Im obigen Beispiel wird ein Record mit der read()-Funktion gelesen wie folgt:  
        >   
        > ~~~perl
          
        
        > binmode HANDLE; # important!  
        > while( read(HANDLE, $bin, 20)){  
        >    ($name, $vname) = unpack("Z10Z10", $bin);  
        > }  
        > 
        
        

        Die "Platzverschwendung" erfolgt nur in der Datei, nicht im RAM, da liegen exact die Werte ohne angehängte Nullen. Für UTF-8-codierte Zeichen bitte entsprechend Platz reservieren.

        Wenn Du es ganz ganz sicher haben willst, das Lesen und Schreiben, lege eine Checksumme am Anfang oder Ende der Datei an. Wenn es nur die Länge ist, genügen 4 byte als checksum (Schablone "N"). Md5-hex-checksummen brauchen 32 byte (256 bit) hier kann außer der Länge noch diese oder jene Angabe in die checksumme gewurstet werden, je nach Bedarf ;-)

        ...mag alles richtig sein, aber - Lichtjahre von meinem Verständnis entfernt...

        Danke Trotzdem....

        Gruß Gary

        1. hi Gary,

          danke fürs Feedback!

          ...mag alles richtig sein, aber - Lichtjahre von meinem Verständnis entfernt...

          Ach was, mal einen langen Winterabend richtig reingekniet, lernst Du das mit Lichtgeschwindigkeit ;-)

          Wenn Du mit Perl so richtig schöne Sachen machen willst, kommt nochn bischen OOP hinzu. Und wenn Du dann eine Webanwendung schreibst, die frei von Race Conditions, transakionssicher und dann auch noch performant ist, denkst Du über das "Erfolgsrezept php + mysql" ein bischen anders nach. Das Problem ist dann nicht mehr die Frage der Datenhaltung sondern die Navigation über große Tabellen mit dem Browser.

          Bitte nicht falsch verstehen, für ein rel. DBMS gibt es keinen Ersatz. Zur Verwaltung von ein paar (tausend) Adressen und Telefonnummern ist es jedoch nicht immer und unbedingt notwendig.

          Gut Nacht,
          Horst Schnarcher