|

Flatfile - Datenbanken
Eine Flatfile-Datenbank auslesen
In eine Datei schreiben
Datei öffnen zum Anfügen von Daten
Ändern und Löschen von Daten in einer
Flatfile-Datenbank
Flatfile-Datenbanken sind die einfachste Möglichkeit,
Daten zu speichern. Sie bestehen aus nichts anderem als strukturiertem
Text.
Eine Flatfile-Datenbank sieht zum Beispiel so aus:
Name:Andrés Ehmann:::Beruf:Diplom
Volkswirt, Magister Artium:::Telefon:030/47301386
Name:Ernst Müller:::Beruf:Diplom Kaufmann:::Telefon:040/4564567
Name:Werner Maier:::Beruf:Diplom Physiker:::Telefon:089/3454443
Der Inhalt ist selbsterklärend. Um das
nachfolgende Beispiel nachzuvollziehen, sollten diese drei
Zeilen unter dem Namen flatfile.txt in dem Ordner abgespeichert
werden, in dem sich auch, das gleich folgende Programm befindet,
dass die Daten ausliest. Diese Flatfile-Datenbank kann dann
mit diesem kleinen Skript ausgelesen werden.
| Eine
Flatfile-Datenbank auslesen |
|
<?
$flatfile=file("flatfile.txt");
foreach ($flatfile as $zeile)
{
$einzelne_Elemente_jeder_Zeile=split(":::",$zeile);
foreach ($einzelne_Elemente_jeder_Zeile
as $einzelteile)
{
print "$einzelteile <br>";
}
print "-----------------------------------------------------<br>";
}
?>
Als Ergebnis erhält man dann, so
denn die Datei flatfile.txt tatsächlich eingerichtet
wurde
Name:Andrés Ehmann
Beruf:Diplom Volkswirt, Magister Artium
Telefon:030/47301386
-----------------------------------------------------
Name:Ernst Müller
Beruf:Diplom Kaufmann
Telefon:040/4564567
-----------------------------------------------------
Name:Werner Maier
Beruf:Diplom Physiker
Telefon:089/3454443
-----------------------------------------------------
Der Befehl split, als Alternative zu explode
oder einer regular expression, wurde bereits unter Funktionen
zum Bearbeiten von Zeichenketten beschrieben. Interessant
ist eigentlich nur noch diese Zeile.
$flatfile=file("flatfile.txt");
Die Funktion file hat folgende Wirkung.
Sie schnappt sich die komplette Datei, die ihr als Parameter
übergeben wird und speichert sie in einen Array, in diesem
Falle also in $flatfile. Hierbei wird jede Zeile der Datei
ein Element des Arrays.
Wir erhalten also folgendes:
$flatfile[0] => ist dann: Name:Andrés
Ehmann:::Beruf:Diplom Volkswirt, Magister Artium:::Telefon:030/47301386
$flatfile[1] => ist dann: Name:Ernst Müller:::Beruf:Diplom
Kaufmann:::Telefon:040/4564567
$flatfile[2] => ist dann: Name:Werner Maier:::Beruf:Diplom
Physiker:::Telefon:089/3454443
Hat man die Datei, lässt sie sich
wie ein Array auslesen, zur foreach-Schleife siehe Schleifen.
Eine alternative Möglichkeit einen Flatfile auszulesen,
sähe so aus.
<?
$datei_handle = fopen("flatfile.txt", "r");
$flatfile = fread($datei_handle, filesize("flatfile.txt"));
fclose ($datei_handle);
$inhalt_in_Zeilen=explode("\n",$flatfile);
foreach($inhalt_in_Zeilen as $wert)
{
$einzelteile=preg_split("/:::/",$wert);
foreach ($einzelteile as $einzelner_wert)
{
print "$einzelner_wert <br>";
}
}
?>
Das Ergebnis ist mit dem oben Abgebildeten
völlig identisch. Wie unschwer zu erkennen, ist aber
die zuletzt dargestellte Methode umständlicher. Betrachten
wir die ersten vier Zeilen genauer.
(1) $datei_handle = fopen("flatfile.txt", "r");
(2) $flatfile = fread($datei_handle, filesize("flatfile.txt"));
(3) fclose ($datei_handle);
(4) $inhalt_in_Zeilen=explode("\n",$flatfile);
(1) Mit der Funktion fopen öffnen wir eine
Datei und zwar zum Lesen (r wie read). Diese geöffnete
Datei weisen wir einem file-handle zu. Alle Operationen, wie
lesen, schreiben oder änfügen (siehe unten) gehen
auf den file-handle und nicht direkt auf die Datei auf die
der file-handle zeigt. (2) Mit fread lesen wir die Datei aus.
Die Funktion fread hat zwei Parameter, den oben generierten
file-handle, und die Anzahl an Bytes, die ausgelesen werden
sollen. Wir wollen die gesamte Datei auslesen, wissen aber
nicht, wie lang diese eigentlich ist. Das ermitteln wir mit
der Funktion filesize. (3) Da wir den Inhalt der Datei nun
in der Skalarvariablen $flatfile haben, können wir die
Verbindung zu file-handle auch wieder schliessen. (4) Wir
splitten am newline Zeichen \n. Das newline Zeichen entseht,
wenn wir die Return-Taste drücken, was wir bei der Eingabe
der Zeilen getan haben, sonst stünden sie nich so brav
untereinander. Wir erhalten übergeben dann jedes Element
dem Array $inhalt_der_Zeilen. Der Array ist dann identisch
wie oben und lässt sich somit auch identisch auswerten.
Explode, split, preg_split sind in diesem Zusammenhang austauschbar.
Die Verwendung aller drei Funktionen hat lediglich didaktische
Gründe.
Es ist somit klar, dass man die Funktion file verwenden sollte,
wenn man lediglich einen Flatfile auslesen will. Die Funktion
fread sollte man verwenden, wenn man lediglich Teile einer
Datei auslesen will, oder eine Datei, die als Binary vorliegt,
wie etwa ein Bild.
Will man ein Bild auslesen, funktioniert das nicht
<?
$bild=file("kirsche.jpg");
foreach ($bild as $schrott)
{
print $schrott;
}
?>
Sehr wohl aber das:
<?
$datei_handle = fopen("kirsche.jpg", "rb");
$bild = fread($datei_handle, filesize("kirsche.jpg"));
fclose ($datei_handle);
print $bild;
?>
Die Funktion file erlaubt das Umstellen
in den binary mode nicht. Nur im binary mode werden Dateien
1 zu 1 übertragen, völlig unabhängig davon,
ob das Betriebssystem damit was anfangen kann oder nicht.
Im Ascii Mode, wird versucht, die Datei systemadäquat
zu interpretieren, was bei Bilder dann zum Absturz führt.
Bei der Verwendung der Funktion fopen kann man angeben, ob
sie im binary-Mode, rb, oder im Ascii-Mode geöffnet werden
soll. Das Bild das in diesem Beispiel verwendet wurde, kann
hier via copy and paste in den passenden Ordner gelegt werden.
Das Ergebnis der Funktion split (explode oder preg_split)
einer Liste übergeben:
Der Vollständigkeitshalber sei noch
gesagt, dass man das Ergebnis der Funktionen split (explode,
preg_split) auch einer Liste übergeben kann.
<?
$flatfile=file("flatfile.txt");
foreach ($flatfile as $zeile)
{
list ($name, $beruf,$telefon)=explode(":::",$zeile);
print "$name <br>";
print "$beruf <br>";
print "$telefon <br>";
print "-----------------------------------------------------<br>";
}
?>
Der exotische Fall: Man kennt die genaue
Länge der Teilbereiche einer Zeile
Kennt man die Anzahl an Bytes, die jede Informationseinheit
einer Zeile ausmacht, dann kann man auch mit fgets eine Datei
auslesen.
Andres Ehmann Dipl. Volkwirt 03047301386 -
Hans Maier Dipl. Ing. Elektr. 040456456666 -
Werner Müller Baufachverkäufer 0894457868 -
Der Block mit dem Namen, mit der Berufsbezeichnung
und mit der Telefonnummer haben jeweis 20 Zeichen. Es wurde
mit Leerzeichen aufgefüllt. Das folgende Beispiel setzt
voraus, dass der Flatfile oben unter dem Namen test.txt in
dem Ordner abgespeichert wird, wo sich auch der PHP Skript
befindet, der ihn ausliest. (Man kann ihn natürlich auch
sonstwo abspeichern, aber dann muss der physikalische Pfad,
relativ oder absolut, angegeben werden.) Die Zeilen wurde,
durch Auffüllen mit Leerzeichen so geschrieben, dass
der Name aus Leerzeichen besteht und genau 13 Bytes (was dann
wiederum 13 Zeichen sind, da jedes Zeichen ein Byte ist) lang
ist. In solch einem Fall, kann man eine Flatfile-Datenbank
auch mit fgets auslesen.
<?
$datei_handle=fopen("test.txt",r);
while(!feof($datei_handle))
{
$name=fgets($datei_handle,20);
print $name;
print "<font color=red> Position des Zeigers ".ftell($datei_handle)."</font>";
print "<br>";
}
fclose($datei_handle);
?>
Das Ergebnis sieht dann so aus:
Andres Ehmann Position des Zeigers
19
Dipl. Volkwirt Position des Zeigers 38
03047301386 Position des Zeigers 57
- Position des Zeigers 70
Hans Maier Position des Zeigers 89
Dipl. Ing. Elektr. Position des Zeigers 108
040456456666 Position des Zeigers 127
- Position des Zeigers 136
Werner Müller Position des Zeigers 155
Baufachverkäufer Position des Zeigers 174
0894457868 Position des Zeigers 193
- Position des Zeigers 198
Was ist passiert ? Wir haben einen file-handle
auf die Datei test.txt generiert. Diesen file-handle haben
wir mit einer while-Schleife ausgelesen. Die while-Schleife
ist solange gelaufen, wie die Funktion feof nicht den Wert
true zurück gegeben hat (bis zum Ende gibt sie immer
false zurück, aber das haben wir mit dem ! negiert).
Wir haben dann jeweils in 20 Bytes Schritten die Zeichenkette
ausgelesen und den Rückgabewert in der Variablen $name
gespeichert. Anschliessend haben wir uns die aktuelle Position
des Zeigers ausdrucken lassen. Er ist 19 weil wir ja bei 0
gestartet sind und 20 Zeichen weitergelaufen sind. Dann haben
wir uns den nächsten Informationsblock, die Berufsbezeichnung,
ausdrucken lassen. Wieder wird bei 0 gestartet und weitergezählt,
sodass wir bei 38 landen. So lesen wir die komplette Zeile
aus. Am Schluss bleibt ein Block übrig, der weniger als
20 Zeichen hat. Der Zeiger bricht aber auf jeden Fall bei
dem newline Zeichen ab, was das Ende der Zeile markiert. Wir
erhalten also noch einen Restblock von 3 Bytes (70 - 57).
In der nächsten Zeile beginnt das Spiel von vorne. Für
die meisten praktischen Anwendungen, gibt es zu diesem Verfahren,
wie oben beschrieben, zahlreiche, wesentlich einfacherer Alternativen.
HTML und PHP Tags entfernen mit getss:
Etwas ähnliches wie getss leistet auch die Funktion strip_tap,
siehe Funktionen zum Bearbeiten von Zeichenketten Um das unten
stehende Skript laufen zu lassen, muss eine Datei htmlwech.htm
mit unten stehendem Inhalt in dem Ordner eingerichtet werden,
in dem sich auch der PHP Skript befindet.
<html><head><title>test</title></head><body>hallo
<img src=kirsche.jpg></body></html>
Will man jetzt alle HTML Tags entfernen,
kann man das mit diesem Skript tun.
<?
$html_seite=fopen("htmlwech.htm",r);
while(!feof($html_seite))
{
$gereinigt=fgetss($html_seite,filesize("htmlwech.htm"));
print $gereinigt;
}
fclose($html_seite);
?>
Das Ergebniss ist dann ein simples testhallo,
da ja alle HTML Tags eliminiert wurden. Die Funktion fgetss
bietet noch optional, ähnlich wie strip_tag, die Möglichkeit
an bestimmte HTML Tags stehen zu lassen. In diesem konkreten
Fall würde es sich zum Beispiel anbieten, den img Tag
stehen zu lassen. Das sieht dann so aus.
<?
$html_seite=fopen("htmlwech.htm",r);
while(!feof($html_seite))
{
$gereinigt=fgetss($html_seite,filesize("htmlwech.htm"),'<img>');
print $gereinigt;
}
fclose($html_seite);
?>
Das Ergebnis als HTML Quelltext sieht
dann so aus
testhallo <img src=kirsche.jpg>
Wie unschwer zu erkennen, wurde der img
Tag nicht eliminiert.
CSV (comma separates files) auslesen
Oben wurde als delimiter, also als Zeichen, dass innerhalb
einer Zeile einen Informationsblock vom anderen trennt, dreimal
der Doppelpunkt gewählt (:::). Obwohl es eigentlich ziemlich
egal ist, gibt es zahlreiche Anwendungen, die das Komma als
delimiter wählen. Bei den meisten Internetanwendungen,
die Eingaben des Users speichern, ist das Komma eher ungeeignet,
weil der User dieses Zeichen selber eingeben kann. Wie dem
auch sei, die Funktion fgetcsv liest, ähnlich wie die
Funktion fgets, eine Datei aus, spaltet aber jede Zeile noch
an einem delimiter und übergibt die Werte in einen Array.
Obwohl also jeder x-beliebige Werst als delimiter übergeben
werden kann, heisst die funktion fgetcsv. Um das Beispiel
laufen zu lassen, muss man folgende Datei in dem Ordner, in
dem auch der PHP Skript liegt unter dem Namen csv.txt abspeichern.
Andres Ehmann, Diplom Volkswirt/Magister der romanischen Philologie,
030-47301386
Heiner Geissler, Rechtsanwalt, 067-345633333
Helmut Kohl, Historiker, 089-3453454444
Auslesen könnte man die Datei mit
folgendem Skript.
<?
$file_handle=fopen("csv.txt",r);
while(!feof($file_handle))
{
$einzelteile=fgetcsv($file_handle,filesize("csv.txt"));
foreach($einzelteile as $block)
{
print "$block <br>";
}
}
fclose($file_handle);
?>
Wie deutlich zu sehen, haben wir nicht
angegeben, an welchem Zeichen, jede Zeile aufgehackt werden
soll. Das müssen wir auch nicht unbedingt, denn der Default-Wert
ist das Komma. Man kann aber auch an einem anderen Zeichen
aufspalten, wie das folgende Beispiel zeigt. Um den Skript
laufen zu lassen, muss man vorher eine Datei sonstiges.txt
mit folgendem Inhalt abspeichern.
Andres Ehmann^Diplom Volkswirt/Magister der romanischen Philologie^030-47301386
Heiner Geissler^Rechtsanwalt^067-345633333
Helmut Kohl^Historiker^089-3453454444
Diese Datei könnte man mit diesem
Skript auslesen.
<?
$file_handle=fopen("sonstiges.txt",r);
while(!feof($file_handle))
{
$einzelteile=fgetcsv($file_handle,filesize("sonstiges.txt"),"^");
foreach($einzelteile as $block)
{
print "$block<br>";
}
}
?>
Anzumerken ist, dass die Funktion fgetcsv
mit einer Kombination von Zeichen als delimiter, z.B. ^^^
oder &&& nicht klarzukommen scheint. Alternativ
hätte man den Skript oben auch so schreiben können.
<?
$file_handle=fopen("sonstiges.txt",r);
while( $einzelteile=fgetcsv($file_handle,filesize("sonstiges.txt"),"^"))
{
foreach($einzelteile as $block)
{
print "$block<br>";
}
}
?>
Man kann sich darüber wundern, dass so
etwas funktioniert, aber die Begründung ist einfach.
Jeder von 0 oder undef verschiedene Wert ist true. Also solange
die fgetcsv Funktion irgendwas zurückgibt, was sie bis
zum Ende ja tut, ist das für die while-Schleife true.
Lesen ist ja ganz nett, aber bevor irgend
jemand was lesen kann, muss irgend jemand was geschrieben
haben. Daten einlesen ist einfacher als Daten rausholen. Es
funktionniert mit diesem Skript.
<?
$string="
Im Windesweben,
war deine Frage nur Träumerei,
nur Lächeln war, was du gegeben,
in dunkler Nacht, ein Glanz entfacht,
nun ist es Herbst,
nun muss ich wohl um dein Aug und Haar,
alle Tage in Sehnen leben";
$datei_handle=fopen("stefan_george.txt",w);
fwrite ($datei_handle,$string);
fclose($datei_handle);
print "Wie sagte schon Mozart ? Das Weib ist das schönste
Ding auf der Welt,".
"Sonate in F Dur für Geigen";
?>
Der Skript führt dazu, dass im gleichen
Ordner, in dem der PHP Skript liegt, eine Datei mit dem Namen
stefan_george.txt eingerichtet wird, die auch tatsächlich
ein Gedicht dieses Dichters enthält. Wie es funktionniert,
ist schnell erklärt. Wir öffnen die Datei zum schreiben,
man achte auf das w wie write. Anschliessend beschreiben wir
die Datei mit der Funktion fwrite. Schreiben, also write ist
hier folgendermaßen zu verstehen. Ist die Datein noch
nicht da, wird sie eingerichtet. Hat die Datei schon Inhalte,
werden diese von den neuen Inhalten überschrieben. Das
heisst, die alten Inhalte sind dann weg. Das heisst im Klartext,
für Gästebücher ist die Option w wie write
ausgesprochen schlecht, weil so ein Gästebuch immer nur
einen Beitrag hätte.
| Datei
öffnen zum Anfügen von Daten |
|
Damit wir in unserer Datenbank einen umfassenden
Überblick über die Lyrik Stefan Georges erhalten,
fügen wir jetzt zu dem ersten Gedicht noch ein weiteres
hinzu.
<?
$string="
Sage mir auf welchem Pfade,
heute sie vorüberschreite,
dass ich aus der reichsten Lade,
zarte Seidenweben hole,
Rosen pflücke und Violen,
dass ich meine Wange reiche,
Schemmel unter ihrer Sohle";
$datei_handle=fopen("stefan_george.txt",a);
fwrite($datei_handle,$string);
fclose($datei_handle);
print "Es ist vollbracht";
?>
Nachdem beide Skripte ausgeführt
wurden, sieht die Datei stefan_george.txt so aus.
Im Windesweben, war deine Frage
nur Träumerei,
nur Lächeln war, was du gegeben,
in dunkler Nacht, ein Glanz entfacht,
nun ist es Herbst,
nun muss ich wohl um dein Aug und Haar,
alle Tage in Sehnen leben
Sage mir auf welchem Pfade,
heute sie vorüberschreite,
dass ich aus der reichsten Lade,
zarte Seidenweben hole,
Rosen pflücke und Violen,
dass ich meine Wange reiche,
Schemmel unter ihrer Sohle
| Ändern
und Löschen von Daten in einer Flatfile-Datenbank
|
|
Für kleine Datenmengen, etwa 1000 Zeilen
ist eine Flatfile-Datenbank ausreichend. Zumindest dann, wenn
keine komplexen Suchalgorithmen, simultanes Löschen/Ändern
von Datensätzen etc. benötigt werden. Meistens will
man aber zumindest die Möglichkeit haben, einzelne Datensätze
zu ändern oder zu löschen, beispielsweise bei Gästebüchern,
wenn einzelne Beiträge "daneben" sind. Das
Problem ist, dass man einzelne Datensätze nicht löschen
kann. Man kann nur den kompletten Flatfile auslesen, die Zeile,
die man verändern oder löschen will bearbeiten und
anschliessend den gesamten Flatfile zurückschreiben.
Bedingung hierfür ist, dass jeder Datensatz eindeutig
charakterisiert ist, also so etwas ähnliches wie einen
"primary key" hat, also einen Spaltenwert, der ihn
eindeutig identifiziert. Nehmen wir an, wir haben einen Flatfile
dieser Art.
Andres Ehmann, Diplom Volkswirt, Berlin, Hallandstrasse 2,1
Heiner Müller, Dichter, Berlin, Brechtgasse 23,2
Ottilie Wagenbrecht, Dipl.Kauffrau, Hamburg,Goldgasse 12,3
Felipe Gonzale, Licenciado en letras, Madrid, Avenida de las
Americas 55,4
Und nehmen wir an, dieser Flatfile ist
unter dem Namen adressen.txt in dem Ordner abgespeichert,
in dem auch der PHP-Skript liegt. Wie deutlich zu sehen, hat
jeder Datensatz am Schluss eine Nummer, die ihn eindeutig
identifiziert. Eine solche Nummer könnten wir ohne weiteres
bei einer online Anwendung für jeden Datensatz kreieren.
Wir hätten dann die Möglichkeit, die Zeile mit der
Nummer 3 mit folgendem Skript zu ändern. Für ein
komplexeres Beispiel siehe Telefondatenbank.
<?
$zu_aendernder_array=file("adressen.txt");
$geaenderter=array();
foreach($zu_aendernder_array as $zeile)
{
list ($name,$Beruf,$stadt,$strasse,$ident)=explode(",",$zeile);
chop($ident);
if ($ident != 3)
{
array_push($geaenderter,"$name,$Beruf,$stadt,$strasse,$ident");
}
}
$datei_handle=fopen("adressen.txt",w);
$fertisch=implode("",$geaenderter);
fwrite($datei_handle,$fertisch);
fclose($datei_handle);
print "Datensatz Nr. 3 wurde gelöscht";
?>
|
 |