Clipper: (Stand: 23.12.2001)

Datenbanken (.DBF) - Memo-Dateien (.DBT) - Indexdateien (.NTX) - Mem-Dateien (.MEM)

0. Erläuterungen:

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
Kennzeichen Benutzung
02H FoxBASE
03H Clipper, dBase, FoxBASE+ ohne Memo-Feld/Datei
07H Visual Objects ohne Memo
30H Visual Foxpro ohne Memo
43H dBASE IV SQL-Tabelle ohne Memo
63H dBASE IV SQL-Systemdatei ohne Memo
83H Clipper, dBase, FoxBASE+ mit Memo-Feld/Datei
87H Visual Objects mit Memo
8BH dBASE IV mit Memo
CBH dBASE IV SQL-Tabelle mit Memo
F5H Visual Foxpro mit Memo
FBH FoxBASE mit Memo
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

Typ

Bedeutung

C

Character

D

Datum

L

Logisch

M

Memofeld

N

Numerisch

Foxpro etc. definieren zusätzliche Typen!
B Double
F Gleitkomma
G Objekt
I Integer
P Bild
T Datum/Zeit
Y Währung
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:

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
Kennzeichen Bedeutung
0600H "normale" Indexdatei, aufsteigend sortiert
0700H "Descend", absteigend sortiert
0900H angeblich "gute" NTX-Datei, wage ich
aber zu bezweifeln
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:
(Satznummer - 1) * Satzlänge (s. 1.1.) + Start (s. 1.1.)
Erinnerung: das erste Byte ist das Löschkennzeichen!

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
Adresse 00 BD:
= Adresse
00 00 04 00
= Satznummer 00 00 00 B1
= Schlüssel '256'
Adresse 00 9C:
= Adresse 00 00 14 00
= Satznummer 00 00 00 35
= Schlüssel '517'
Adresse 00 B2:
= Adresse 00 00 08 00
= Satznummer 00 00 00 05
= Schlüssel '872'
Adresse 00 A7:
= Adresse
00 00 10 00
= Satznummer 00 00 00 00
= Schlüssel 00H
Level 1 Adresse: 00 00 04 00
Anzahl: 26H(1 addieren!)
Eintragszeiger 1:
00 F4
...
Eintragszeiger 27H: 00 E9
Adresse 00 F4:
= Adresse
00 00 24 00
= Satznummer 00 00 01 99
= Schlüssel '100'
Adresse 00 E9:
= Adresse 00 00 08 20
= Satznummer 00 00 03 A5
= Schlüssel '254'

...

Adresse: 00 00 10 00
Anzahl: 31H (1 addieren!)
Eintragszeiger 1: 00 E9
...
Eintragszeiger 32H: 01 A0
Adresse 00 E9:
= Adresse 00 00 40 00
= Satznummer 00 00 02 07
= Schlüssel '880'
Adresse 01 A0:
= Adresse 00 00 06 24
= Satznummer 00 00 04 01
= Schlüssel '990'
Level 2 Adresse: 00 00 24 00
Anzahl: 36H
Eintragszeiger 1:
00 C8
...
Eintragszeiger 36H: 01 20
Adresse 00 C8:
= Adresse 00 00 00 00
(unterster Level!)
= Satznummer 00 00 01 99
= Schlüssel ' 10'
Adresse 01 20:
= Adresse 00 00 00 00
(unterster Level!)
= Satznummer 00 00 03 55
= Schlüssel ' 99'
... Adresse: 00 00 08 20
Anzahl: 28H
Eintragszeiger 1:
00 D3
...
Eintragszeiger 28H: 00 FF
Adresse 00 D3:
= Adresse 00 00 00 00
(unterster Level!)
= Satznummer 00 00 03 77
= Schlüssel '154'
Adresse 00 FF:
= Adresse 00 00 00 00
(unterster Level!)
= Satznummer 00 00 03 05
= Schlüssel '250'
... Adresse: 00 00 06 24
Anzahl: 38H
Eintragszeiger 1:
00 DE
...
Eintragszeiger 38H: 02 33
Adresse 00 DE:
= Adresse 00 00 00 00
(unterster Level!)
= Satznummer 00 00 01 88
= Schlüssel '881'
Adresse 02 33:
= Adresse 00 00 00 00
(unterster Level!)
= Satznummer 00 00 03 C5
= Schlüssel '979'

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
.

Typ

Bedeutung

C

Character

D

Datum

L

Logisch

N

Numerisch

  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
ist mitgerechnet

D

Datum, immer 8 Bytes, gespeichert als Tageszahl im IEEE-Format, nicht so einfach lesbar
nach Umwandlung muß man 2415021 abziehen, um die Anzahl Tage zwischen diesem
Datum und dem 1.1.1900 zu bekommen.

L

Logisch, 1 Byte, 01H = .true., 00H = .false.

N

Numerisch, Zahlen, immer 8 Bytes, gespeichert als IEEE-Zahl, nicht so einfach lesbar
Nachkommastellen und Länge s. o.

4.3. Schlußbyte: CTRL-Z = STRG-Z = ASCII 26 = 01AH

Programm zum Dump einer Mem-Datei

Programmierungs-Seite

Startseite

(www.zelczak.com/clipp_de.htm)