Homepage Inspire-world | Forum
CGI/Perl Workshops Verarbeiten von Textdatenbanken

 Inhaltsverzeichnis/Workshops Übersichtsseite/Verarbeiten von Textdatenbanken
Vorwort
In eine Datei schreiben
Eine Zeile aus einer Datei löschen
Eine editierte Zeile einer Text DB zurückschreiben in Datei
Eine Datei gleichzeitig aktualisieren, schreiben und sortieren
Daten mit bestimmten Kriterien verarbeiten

Vorwort:

In eine Datei schreiben ist leicht, schwieriger ist es da schon an die Dateiinhalte heranzukommen um diese sicher zu editieren, zu aktualisieren oder zu löschen. Ich werde hier einige Praxisbezogene Beispiele vorstellen die sich mit der Problematik befassen. Grundkenntnisse sollten aber hier schon vorhanden sein um die Workshops zu verstehen. Fragen dazu werden natürlich gern im Forum beantwortet.


Top
In eine Datei schreiben

Grundsätzlicher Aufbau
Öffnet man eine Datei mit >> bedeutet dass das hier die Daten am Dateiende angehängt werden. Hiermit > wird die Datei hingegen überschrieben.
open (FILE, ">>$dateipfad/daten.dat") or scripterror("Fehler: Kann daten.dat nicht oeffnen!",$!);
flock (FILE, 2);
print FILE "$id|$email|$url|$name\n";
close FILE;
Wenn man von vornherein plant die Dateiinhalte später editieren oder löschen zu wollen ist es eine gute Idee eine eindeutige ID für jede Zeile zu vergeben. Dies kann eine Kombination von Zufallszeichen, die Zeit, ein Counterwert oder ähnliches sein. Mit dieser ID ist dann eine eindeutige Zuordnung leicht herzustellen.



Top
Eine Zeile aus einer Datei löschen

Grundsätzlicher Aufbau
open (DATEN, "+>>$dateipfad/daten.dat") or scripterror("Fehler: Kann daten.dat nicht oeffnen!",$!);
flock (DATEN, 2); 
seek DATEN, 0, 0;
my @daten = <DATEN>;
my @neue_daten = ();
foreach $daten (@daten) {
chomp $daten; 
($eintragsid,$email,$url,$name) = split(/\|/, $daten);
if ($eintragsid ne $id) {
$daten = "$daten\n";
push @neue_daten, $daten;
}
}
seek DATEN, 0, 0;
truncate DATEN, 0;
print DATEN @neue_daten;
flock (DATEN, 8);
close DATEN;
Wie funktioniert's?

Hier wird die Datei zum aktualisieren geöffnet, dann der Dateizeiger mittels seek DATEN, 0, 0; an den Anfang der Datei gesetzt.

Nun wird ein neues, leeres Array definiert mit my @neue_daten = ();

In der nachfolgenden foreach Schleife foreach $daten (@daten) { werden die Dateizeilen durchlaufen und das \n am Zeilenende mittels chomp $daten; entfernt.

Dem schließt sich das splitten der Zeilen an ($eintragsid|$email|$url|$name) = split(/\|/, $daten);.

In dem Codeblock:
if ($id ne $eintragsid) {
$daten = "$daten\n";
push @neue_daten, $daten;
}
werden nun die Dateiinhalte die nicht (ne) mit der ID übereinstimmen in das neue Array ge"push"t.

Nun wird der Dateizeiger wieder an den Dateianfang positioniert, der Dateiinhalt komplett gelöscht mit truncate DATEN, 0; und der Inhalt des Arrays in die Datei print DATEN @neue_daten; geschrieben.



Top
Eine editierte Zeile einer Text DB zurückschreiben in Datei

Grundsätzlicher Aufbau
open(DATEN, "<$dateipfad/daten.dat") or scripterror("Fehler: Kann daten.dat nicht oeffnen!",$!); 
flock(DATEN,2);
while(<DATEN> ){
(@dateiinhalt) =split(/\|/, $_);
if ($dateiinhalt[0] eq $eintragsid){
push(@new, "$eintragsid|$email|$url|$name\n");
} else {
push(@new,$_);
}
}
close(DATEN);

open(NEUEDATEN, ">$dateipfad/daten.dat") or scripterror("Fehler: Kann daten.dat nicht oeffnen!",$!);  
flock(NEUEDATEN,2); 
print NEUEDATEN @new;
close(NEUEDATEN);
Wie funktioniert's?

Nach dem öffnen der Datei wird mittels einer while Schleife das Array @dateiinhalt durchlaufen und die Zeilen (@dateiinhalt) =split(/\|/, $_); gesplittet. Da die ID hier am Zeilenanfang, besser gesagt im Array die Position 0 hat, wird nun mittels if ($dateiinhalt[0] eq $eintragsid){ verglichen welche Zeile aktualisiert werden soll.

Ist diese ermittelt wird auch hier der Inhalt in das Array gepusht. push(@new, "$eintragsid|$email|$url|$name\n");

Alles andere was nicht mit der ID übereinstimmt wird auch in das Array @new "gepusht", aber eben unverändert.

Nach dem schließen der Datei wird diese erneut geöffnet und der Inhalt des Arrays @new in die Datei geschrieben. Da die Datei nur mit > geöffnet wird werden die Dateinhalte komplett mit den neuen Dateinhalten ersetzt.



Top
Eine Datei gleichzeitig aktualisieren, schreiben und sortieren

Grundsätzlicher Aufbau
#!/usr/bin/perl
use CGI::Carp qw(fatalsToBrowser);

# Grafik die ausgegeben wird, diese wird deshalb verwendet weil
# hier ja nur etwas geloggt werden soll und keine HTML ausgabe
# erfolgen soll.
$image = "http://www.inspire-net.de/inspire.gif";

# Den Browser aus dem ENV Wert holen
$browser = "$ENV{'HTTP_USER_AGENT'}";


# Die Datei öfnen zum lesen und schreiben mit +< 
open(LOGDB,"+<$dateipfad/daten.dat") or scripterror("Fehler: Kann daten.dat nicht oeffnen!",$!); 
flock(LOGDB,2);
seek(LOGDB,0,0);
@DATEI = <LOGDB>;
$Zeilen = @DATEI;

# Die Datei mittels einer while Schleife durchlaufen...
$i = 0;
$gefunden = 0;
while ($i <= $Zeilen) {
($counter,$browserda) = split(/\|/,$DATEI[$i]);
chomp($browserda);
# Wenn Browser schon als Wert vorhanden
if ($browserda eq $browser) {
$gefunden = 1;
# Counter hochzählen
$counter++;
$DATEI[$i] = "$counter|$browser\n";
}
$i++;
}
# Ist Browser noch nicht vorhanden dann eintragen
if (!$gefunden) {
push @DATEI, "1|$browser\n";
}

# Datei sortieren nach Häufigkeit der Browser
@DATEI = sort {($b =~ /(\d+)/)[0] <=> ($a =~ /(\d+)/)[0]} @DATEI;

seek(LOGDB,0,0);
truncate(LOGDB,tell(LOGDB));
print(LOGDB @DATEI);
flock(LOGDB, 8);                
close(LOGDB);

# Ausgabe der Grafik
print "Location: $image\n\n";
Wie funktioniert's?

Da hier vieles analog der vorangegangenen Beispiele ist were ich hier nur auf einige Punkte eingehen.

In diesem Beispiel wird eine Datei geöffnet, durchlaufen mit einer while Schleife, dann entweder ein Counter hochgezählt oder ein neuer Eintrag geschrieben. Vor dem zurückschreiben der Inhalte wird der ganze Dateiinhalt noch sortiert.

Das sortieren des Dateiinhaltes muss nicht zwingend erfolgen, ist aber eine gute vorarbeit wenn man aus der Datei eine Topliste erstellen will. Das sortieren geschieht hier mittels sort Befehls der zusätzlich mit einem Regulären Ausdruck verbunden ist.
@DATEI = sort {($b =~ /(\d+)/)[0] <=> ($a =~ /(\d+)/)[0]} @DATEI;



Top
Daten mit bestimmten Kriterien verarbeiten

Grundsätzlicher Aufbau
Dieses Beispiel ist ähnlich dem aus "Eine Zeile aus einer Datei löschen" was weiter oben behandelt wurde. Hier soll es aber nicht um das löschen nur einer Zeile gehen, es sollen mehrere Zeilen einer Datei nache einem festgelegten Kriterium in eine andere Datei verschoben werden.

Praktische Anwendung wäre das löschen von z.B. Userdaten nach einem festgelegten Zeitraum.

open (DATEN, "+>>$dateipfad/daten.dat") or scripterror("Fehler: Kann daten.dat nicht oeffnen!",$!); 
flock (DATEN, 2); 
seek DATEN, 0, 0;
my @daten = <DATEN>;

# Zwei neue Arrays definieren
my @neue_daten = ();
my @geloeschte = ();
foreach $daten (@daten) {
chomp $daten; 
($eintragsid,$ablauf,$email,$url,$name) = split /\|/, $daten;

# Vergleichen der Datumswerte die in der Datei stehen
if ($aktuelles_datum < $ablauf) {
$daten = "$daten\n";

# Inhalte entsprechend der Vorgae in die Arrays pushen
push @neue_daten, $daten;
} else {
$olddaten = "$daten\n";
push @geloeschte, $olddaten;
}
}
seek DATEN, 0, 0;
truncate DATEN, 0;
print DATEN @neue_daten;
flock (DATEN, LOCK_UN);
close DATEN;

# Hier wird der Inhalt des Arrays @geloeschte in eine neue Datei geschrieben.
open (ALTEDATEN, ">>$dateipfad/daten.temp") or scripterror("Fehler: Kann daten.temp nicht oeffnen!",$!); 
flock (ALTEDATEN, 2);
print ALTEDATEN @geloeschte;
close ALTEDATEN;
chmod(0777, "$dateipfad/daten.temp");
Wie funktioniert's?

Hier wird wie im Beispiel "Eine Zeile aus einer Datei löschen" vorgegangen, der Unterschied besteht hier darain das zwei leere Arrays angelegt werden die Daten aufnehmen sollen.

Bei $aktuelles_datum < $ablauf wird nun der Datum verglichen, das was kleiner als der Ablaufdatum ist wird behalten und in das Array @neue_daten gepusht, was darüber liegt in das Array @geloeschte. Ideal zum vergleichen von Datumswerten ist die hier vorgestellte Datumsroutine Diese kann den Datum in "Normalform" - also z.B. 22.9.2003 liefern und auch als Tageszahl z.B. 2452606. Mit diesen Zahlenwerten lässt es sich hervorragend rechnen. Will man z.B. Eintröäge nach 30 Tagen verfallen lassen, oder wie hier in eine Archivdatei schreiben, braucht man nur zu der aktuellen Tageszahl 30 addieren.



Top

 Zum Inhaltsverzeichnis/Workshops Übersichtsseite/Verarbeiten von Textdatenbanken
Autor: Helmut Walter Homepage Inspire-world Fragen, Anregungen und Hinweise bitte in das Forum

Valid HTML 4.0! Valid CSS!