Datenbanken (.DBF) - Memo-Dateien (.DBT) - Indexdateien (.NTX) - Mem-Dateien (.MEM)
0. Erläuterungen:
Die Byte-Nummer
ist für C/C++-Programme gedacht, die bei der Zählung
(z. B. bei char cText[]) ja mit 0 beginnen, die Stelle
beginnt jedoch
(z. B. für Clipper Substring nach Lowlevel-Zugriff) bei
1.
Art W = Wort, 2 Bytes, höchstwertiges Byte ist hinten
Art DW =
Doppelwort, 4 Bytes, Reihenfolge: niedrigstes,
zweitniedrigstes,
zweithöchstes, höchstes Byte
1. Struktur von Clipper-Datenbanken
(Anmerkungen zu anderen Systemen sofern bekannt):
1.1. Kopf (32 Bytes):
Bezeichnung | Byte | Stelle | Länge | Art | Inhalt | ||||||||||||||||||||||||||
Kennzeichen | 0 | 1 | 1 | Byte |
|
||||||||||||||||||||||||||
Jahr | 1 | 2 | 1 | Byte | Jahr letzte Änderung, nur zweistellig! | ||||||||||||||||||||||||||
Monat | 2 | 3 | 1 | Byte | Monat letzte Änderung | ||||||||||||||||||||||||||
Tag | 3 | 4 | 1 | Byte | Tag letzte Änderung | ||||||||||||||||||||||||||
Anzahl | 4 | 5 | 4 | DW | Anzahl Sätze | ||||||||||||||||||||||||||
Start | 8 | 9 | 2 | W | Adresse des Beginns der
Daten (Zählung beginnt mit 0!) |
||||||||||||||||||||||||||
Satzlänge | 10 | 11 | 2 | W | Satzlänge (inkl. Löschbyte, "deleted flag") | ||||||||||||||||||||||||||
12 | 13 | 16 | Byte | reserviert, egal, immer 00H? | |||||||||||||||||||||||||||
28 | 29 | 1 | Byte | Visual Foxpro: 01H - strukturierte CDX-Datei vorhanden 02H - Memofeld vorhanden (?) 04H - Datenbank (DBC) |
|||||||||||||||||||||||||||
29 | 30 | 1 | Byte | Visual Foxpro: Code-Seitenmarkierung | |||||||||||||||||||||||||||
30 | 31 | 2 | W | reserviert, egal, immer 00H? |
1.2. Feldeinträge (32 Bytes), je ein Eintrag pro existierendem Feld:
Bezeichnung | Byte | Stelle | Länge | Art | Inhalt | ||||||||||||||||||||||||||||
Feldname | 0 | 1 | 11 | Byte | Feldname, endet mit 00H, danach evtl. irgendwelcher Schmutz |
||||||||||||||||||||||||||||
Feldtyp | 11 | 12 | 1 | Byte |
|
||||||||||||||||||||||||||||
Feldposition | 12 | 13 | 4 | DW | Position Feld im Satz,
bei Clipper nicht benutzt aber höchstwahrscheinlich bei Foxpro |
||||||||||||||||||||||||||||
Feldlänge | 16 | 17 | 1 | Byte | Feldlänge | ||||||||||||||||||||||||||||
FeldNKST | 17 | 18 | 1 | Byte | Nachkommastellen | ||||||||||||||||||||||||||||
bei Clipper
wird für Feldtyp 'C' Feldlänge und FeldNKST zusammen
als Art 'W' als Feldlänge für Felder benutzt, die größer als 255 Zeichen sind. Effektive Länge: FeldNKST * 256 + Feldlänge Visual Foxpro: Feldtyp 'C' hat maximale Länge von 254 |
|||||||||||||||||||||||||||||||||
18 | 19 | 14 | Byte | bei Clipper unbenutzt Visual Foxpro: 01H - Systemspalte (für Benutzer unsichtbar) 02H - Feld darf NULL enthalten 04H - Binär (bei Typ C und M) |
1.3. Ende Kopf:
Clipper: zwei Bytes: ASCII 13 = 0DH und ASCII 0 = 00H
Foxpro: ein
Byte: ASCII 13 = 0DH, Visual Foxpro reserviert z. B.
manchmal noch
263 weitere Bytes bis zum eigentlichen Datenbeginn,
sie sind aber im Feld "Start" (DW Byte 8 und 9)
berücksichtigt).
Falls vorhanden, folgt direkt nach diesem Byte der Name
der DBC-Datei, der diese
DBF-Datei zugeordnet wurde.
1.4. Satz:
Die erste Stelle
beinhaltet immer ein Leerzeichen (Blank, " ", ASCII 32,
020H)
für nicht gelöschte Sätze und einen Stern ("*",
ASCII 42, 02AH) für gelöschte.
Dieses Zeichen ist bei der Feldlänge - Wort (Byte 10 und 11) -
bereits berücksichtigt!
Anschließend folgen die Feldinhalte. Sie stehen ohne
Trennungszeichen direkt
hintereinander.
Maximal 1 Milliarde Sätze pro Datenbank!
Feldinhalte:
Typ |
Bedeutung |
C |
Character, Zeichen, mit Leerstellen aufgefüllt falls nötig |
D |
Datum, immer 8 Bytes, gespeichert als JJJJMMTT |
L |
Logisch, 1 Byte, gespeichert als "T" oder "F" |
M |
Memo, 10-Byte-Zeiger auf den ersten 512-Byte-Block in der DBT-Datei |
N |
Numerisch, Zahlen, gespeichert mit Dezimalpunkt, nicht Komma! |
1.5.
Datenende: ein Byte, CTRL-Z = STRG-Z = ASCII 26 = 1AH.
Hinweis: Dieses Byte kann auch fehlen!
1.6. Programmierbeispiel in Clipper
1.7. Programmierbeispiel in C
2. Struktur von Clipper-Memo-Dateien (.DBT):
2.1. Kopf (512 Bytes):
Bezeichnung | Byte | Stelle | Länge | Art | Inhalt |
Anzahl | 0 | 1 | 4 | DW | Nächste zu vergebende
Blocknummer bzw. Anzahl der vergebenen 512-Byte-Blöcke (letzter Block kann nur teilweise gefüllt sein, d. h. die Dateigröße muß nicht durch 512 teilbar sein!) |
4 | 5 | 508 | Bytes | egal, reserviert, enthalten evtl. Schmutz |
2.2. Inhalt:
Die Adresse der
Daten in der DBT-Datei für einen bestimmten Satz aus der DBF-Datei
erhält man,
in dem man den oben erwähnten 10-Byte-Zeiger heraussucht und mit
512 multipliziert.
Dort stehen die Daten und sind relevant bis vor das erste CTRL-Z
(STRG-Z, ASCII 26 = 01AH).
Maximalgröße Daten für einen Satz = 64 KB = 128 Blöcke á 512
Bytes!
Maximalgröße DBT-Datei = 32 MB!
Hinweis: Hat ein Satz ein leeres Memo-Feld,
so werden trotzdem 512 Bytes belegt.
Hinweis: Vergrößert sich ein Memo-Feld
über die nächste Block-Grenze hinaus, so werden die
Daten ans Ende der DBT-Datei kopiert und die bisherigen Blöcke
werden einfach nicht mehr
benutzt. Dieser Speicherplatz ist verloren, bis man ein Pack oder
ein Copy durchführt.
Selbstverständlich bekommt man den Speicherplatz auch bei einem
Zap wieder zurück <vbg>.
3. Struktur von Clipper-Indexdateien (.NTX):
Clipper-Indexdateien
benutzen einen modifizierten B+-Baum-Algorithmus.
Normalerweise haben nur die Blätter (Leafs) Schlüsselwerte (Keys).
Bei Clipper haben auch die Wurzel (Root) und die Äste (Nodes)
Schlüsselwerte und Satznummern.
Eine NTX-Datei
hat genau einen Kopf-Block und Daten in mindestens einem und
maximal drei Levels
in Abhängigkeit vom Produkt von der Anzahl von Sätzen und der
Schlüssel-Länge + 8.
Alle Daten werden in Blöcken von 1024 Bytes abgespeichert.
Kopf-Block und Level-1-Block sind genau einmal vorhanden.
Level-2- und Level-3-Blöcke sind nur bei Bedarf und dann
beliebig oft vorhanden.
Die maximale Länge eines Indexschlüssels beträgt 250 Zeichen.
3.1. Kopf (1024 Bytes):
Bezeichnung | Byte | Stelle | Länge | Art | Inhalt | ||||||||
Kennzeichen | 0 | 1 | 2 | W |
|
||||||||
Version | 2 | 3 | 2 | W | angeblich Clipper-Version,
das kann aber nicht sein, da ich mindestens 20 verschiedene Werte in meinen DBF's (alle Clipper 5.2e) gefunden habe. |
||||||||
ErsteSeite | 4 | 5 | 4 | DW | Adresse der ersten Seite | ||||||||
FreieSeite | 8 | 9 | 4 | DW | Beginn der Verkettung
der freien Seite (s. 3.4.), falls keine freien Seiten vorhanden sind, dann 0 |
||||||||
Eintragslänge | 12 | 13 | 2 | W | Länge eines
Indexeintrages = Schlüssellänge + 8 (4 Bytes Adresse nächster Indexblock + 4 Bytes Satznummer in DBF-Datei, s. u.) |
||||||||
Schlüssellänge | 14 | 15 | 2 | W | Länge des Schlüssels, nicht des Schlüsselausdruckes! | ||||||||
Dezimalstellen | 16 | 17 | 2 | W | Dezimalstellen, falls im Index vorhanden | ||||||||
MaxEinträge | 18 | 19 | 2 | W | Maximale Anzahl der Indexeinträge pro Indexseite | ||||||||
MinEinträge | 20 | 21 | 2 | W | Minimale Anzahl der
Indexeinträge pro Indexseite, benötigt, um den Indexbaum auszugleichen |
||||||||
Schlüssel | 22 | 23 | 257 | Bytes | Schlüsselausdruck, beendet mit 00H, Rest egal, Schmutz | ||||||||
Unique | 279 | 280 | 1 | Byte | Unique Index = 01H, 00H sonst | ||||||||
4 | 5 | 744 | Bytes | egal, reserviert, enthalten evtl. Schmutz |
3.2. Level 1-3 (1024 Bytes):
Bezeichnung | Byte | Stelle | Länge | Art | Inhalt |
Anzahl | 0 | 1 | 2 | W | Anzahl gültiger
Indexeinträge Achtung: Ist der Level nicht der unterste, so muß hier 1 addiert werden. Warum? Ist halt so! |
Eintragszeiger | 2 | 3 | 2 | W | n * Eintragszeiger, n =
MaxEinträge (s. vorige Tabelle) Achtung: wahrscheinlich sind viele Einträge gefüllt, gültig sind nur die, die obiger Anzahl entsprechen! Zeiger gilt innerhalb des Blockes! |
Indexeinträge | n *
Indexeintrag, n = MaxEinträge (s. 3.1.) Struktur Indexeintrag s. (3.3.) Achtung: wahrscheinlich sind viele Einträge gefüllt, gültig sind nur die, die obiger Anzahl entsprechen! |
3.3. Indexeintrag (8 Bytes + Schlüssellänge):
Bezeichnung | Byte | Stelle | Länge | Art | Inhalt |
Adresse | 0 | 1 | 4 | DW | Adresse = 0, falls
unterster Level, ansonsten die Adresse des Blockes des nächsten Levels |
Satznummer | 4 | 5 | 4 | DW | Falls Satznummer # 0,
dann findet man in der DBF-Datei unter dieser Satznummer den Satz mit nachfolgendem Schlüssel |
Schlüssel | 8 | 9 | Schlüssel mit der Länge aus (3.1.), ohne 00H! |
Der Schlüssel
eines Indexeintrages (nicht unterster Level!) ist echt größer
als alle Schlüssel
des untergeordneten Blockes, dessen Adresse sich im selben
Indexeintrag befindet.
Der letzte
Indexeintrag des obersten Levels hat einen leeren Schlüssel, 00H.
Im zugehörigen, untergeordneten Block befinden sich die höchsten
Schlüssel!
3.4. Freie Blöcke:
Der Theorie
nach werden freie Blöcke in der Indexdatei beim Freiwerden
verkettet und falls nötig wiederverwendet
Die Nummer des ersten freien Blockes befindet sich im Kopf (s. 3.1.).
Ich habe allerdings noch nie gesehen, dass Clipper wirklich freie
Blöcke hat.
Vielleicht packe ich meine Dateien dafür auch zu oft?!
3.5. Zugriff auf die Daten in der DBF anhand der Satznummer aus der NTX-Datei:
Die
Adresse des Satzes in der DBF erhält man nach folgender
Formel: |
3.6. Beispiel einer Indexdatei (alle Werte hexadezimal):
Kopf | Adresse 1. Seite: 00 00 0C 00 Schlüssellänge: 3 Maximale Einträge pro Seite: 4C Mindestanzahl Einträge: 26 Schlüsselausdruck: STR(ART_NR,3) Unique: True |
|||||||||||||||||||
Level 0 | Adresse: 00 00 0C 00 Anzahl: 03 (1 addieren, da nicht unterster Level!) Eintragszeiger 1: 00 BD Eintragszeiger 2: 00 9C Eintragszeiger 3: 00 B2 Eintragszeiger 4: 00 A7
|
|||||||||||||||||||
Level 1 | Adresse: 00 00 04 00 Anzahl: 26H(1 addieren!) Eintragszeiger 1: 00 F4 ... Eintragszeiger 27H: 00 E9
|
... |
Adresse: 00 00 10 00 Anzahl: 31H (1 addieren!) Eintragszeiger 1: 00 E9 ... Eintragszeiger 32H: 01 A0
|
|||||||||||||||||
Level 2 | Adresse: 00 00 24 00 Anzahl: 36H Eintragszeiger 1: 00 C8 ... Eintragszeiger 36H: 01 20
|
... | Adresse: 00 00 08 20 Anzahl: 28H Eintragszeiger 1: 00 D3 ... Eintragszeiger 28H: 00 FF
|
... | Adresse: 00 00 06 24 Anzahl: 38H Eintragszeiger 1: 00 DE ... Eintragszeiger 38H: 02 33
|
4. Struktur von Clipper-Mem-Dateien (.MEM):
Für jede
mit "SAVE TO" gespeicherte Variable gibt es einen Kopf
(4.1.), der den Feldeinträgen der DBF-Datei (s. 1.2) sehr
gleicht.
Hinter dem Kopf werden Daten (variabler Länge, in Abhängigkeit
vom Datentyp) wie untenstehend (4.2.) angehängt.
Ende der Informationen s. 4.3.
4.1. Kopf für Variable:
Bezeichnung | Byte | Stelle | Länge | Art | Inhalt | ||||||||||
Variablenname | 0 | 1 | 11 | Byte | Variablenname, endet mit
00H, danach evtl. irgendwelcher Schmutz |
||||||||||
Variablentyp | 11 | 12 | 1 | Byte | Hier
ist das Highbit gesetzt, man muß also 128 von diesem Wert abziehen, um den Typ zu bekommen.
|
||||||||||
12 | 13 | 4 | DW | egal, reserviert | |||||||||||
Variablenlänge | 16 | 17 | 1 | Byte | Variablenlänge | ||||||||||
VariablenNKST | 17 | 18 | 1 | Byte | Nachkommastellen | ||||||||||
für
Variablentyp 'C' wird Variablenlänge und VariablenNKST
zusammen als Art 'W' als Variablenlänge für Variablen benutzt, die größer als 255 Zeichen sind. Effektive Länge: VariablenNKST * 256 + Variablenlänge |
|||||||||||||||
18 | 19 | 14 | Byte | egal, reserviert, unbenutzt? |
4.2. Inhalt der Variablen, Daten:
Typ |
Bedeutung |
C |
Character,
soviele Stellen wie im Längenfeld festgehalten, das
abschließende Byte mit 00H |
D |
Datum,
immer 8 Bytes, gespeichert als Tageszahl im IEEE-Format,
nicht so einfach lesbar |
L |
Logisch, 1 Byte, 01H = .true., 00H = .false. |
N |
Numerisch,
Zahlen, immer 8 Bytes, gespeichert als IEEE-Zahl, nicht
so einfach lesbar |
4.3. Schlußbyte: CTRL-Z = STRG-Z = ASCII 26 = 01AH
Programm zum Dump einer Mem-Datei
(www.zelczak.com/clipp_de.htm)