Falsche Feldgrößen beim Einlesen einer DBF-Datei

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
Halvar
Beiträge: 58
Registriert: So 16. Mär 2008, 23:40
OS, Lazarus, FPC: Debian Lenny (L 0.9.28-2 FPC 2.2.4)
CPU-Target: 64Bit
Wohnort: Brake/Unterweser

Falsche Feldgrößen beim Einlesen einer DBF-Datei

Beitrag von Halvar »

Hallo,

ich schreibe gerade ein Tool um Dbf-Dateien zu erstellen bzw. zu ändern. Das erstellen ist kein Problem. NUr mir jetzt aufgefallen, wenn ich die Datei wieder einlese und mir die Felder anzeigen lasse, dann werden einige Feldgrößen nicht korrekt angezeigt. Insbesonders ein Numerisches Feld, welches ursprünglich mit Size=11 und Precision=4 angelegt wurde, wird beim wieder einlesen mit 8 und 4 angegeben. Wenn ich mir jedoch das Dbf-File Im Hexeditor ansehe, ist dort die Feldgröße korrekt mit 11 (0x0b) angegeben.
Das Einlesen erfolgt so:

Code: Alles auswählen

DBA.Close;
  DBA.TableName:=aName;
  DBA.Open;
  grdEdtFields.RowCount:=1;
  for i:=0 to DBA.FieldDefs.Count-1 do begin
    grdEdtFields.RowCount:=grdEdtFields.RowCount+1;
    y := grdEdtFields.RowCount-1;
    FFld    := DBA.Fields[i].FieldName;
    FTyp    := DBA.Fields[i].DataType;
    FSize   := DBA.Fields[i].DataSize;
    FPrec   := DBA.FieldDefs.Items[i].Precision;
    if ((FPrec < 0) and (FSize > 0)) then begin
      FSize := FSize + FPrec;
      FPrec := 0;
    end;
    with grdEdtFields do begin
      //Felddaten ins Grid eintragen
      Cells[0,y] := IntToStr(i+1);
      Cells[1,y] := FFld;
      Cells[2,y] := TranslateTyp(FTyp);
      Cells[3,y] := IntToStr(FSize);
      Cells[4,y] := IntToStr(FPrec);
      Cells[5,y] := '';
    end;
    txtRecSize.Text := IntToStr(CalcRecSize);
  end;
  DBA.Close;
Was auch merkwürdig ist, ist dass die Feldlänge bei Character-Felder immer eins zu groß ist. Wobei Precision -1 ist. Um also die richtige Feldgröße bei Character-Feldern zu bekommen, muss ich Precison von der Feldgröße abziehen.

Hat jemand eine Idee was da falsch läuft?

Gruß
Halvar

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Es gibt bei DBase maximale Feldnamenlängen soweit mir bekannt ist die bei 10 es kann aber sein das sich das je nach Tablelevel unterscheidet.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Halvar
Beiträge: 58
Registriert: So 16. Mär 2008, 23:40
OS, Lazarus, FPC: Debian Lenny (L 0.9.28-2 FPC 2.2.4)
CPU-Target: 64Bit
Wohnort: Brake/Unterweser

Beitrag von Halvar »

Es geht nicht um die Länge des Feldnamens, sondern um die Größe des Feldes (Size).

Ich habe auch das hier im Forum vorgestellte Programm dbmaker ausprobiert. Da wurde mir die Feldgröße des numerischen Feldes sogar nur mit 0 (NULL) angezeigt!

Ich finde das ganze sehr, sehr merkwürdig.

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Wenn ein Numerisches feld keine feldgrösse unterstützt, macht das durchaus sinn.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Halvar
Beiträge: 58
Registriert: So 16. Mär 2008, 23:40
OS, Lazarus, FPC: Debian Lenny (L 0.9.28-2 FPC 2.2.4)
CPU-Target: 64Bit
Wohnort: Brake/Unterweser

Beitrag von Halvar »

Mmmm, es ist ja nett das mir hier überhaupt jemand antwortet, aber hast du dich mal mit DBF beschäftigt? Dann schau dir mal eine DBF-Datei mit einem ganz normalen Editor an. Dann würdest du sehen, dass du alle Daten lesen kannst. Zahlen, ganze und gebrochene, werden nicht Binär gespeichert, sondern ganz normal als Ascii. Insofern macht eine Feldgröße schon einen Sinn ;-)

Ich habe inzwischen festgestellt, dass die Feldgröße beim wieder einlesen immer 8 ist. Egal, ob ich vorher einen kleineren, oder größeren Wert angegeben habe.

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Ich hab mich sogar ziemlich viel damit beschäftigt, brauchte allerdings nie die feldgrössen nach dem anlegen einer Tabelle. Wie auch immer ich hab eben mal schnell eine tabelle im lazarus geöffnet und siehe da, dort werden die feldgrössen korrekt angezeigt der fehler liegt also definitiv nicht bei TDbf.

Es spielt auch keine Rolle wie Daten intern in der Datenbank gespeichert werden ein ftInteger Feld hat immer Grösse 0 zu haben denn die Länge ist durch den feldtyp vorgegeben. Da dürfte TDbf gar keinen Einfluss drauf haben das ist schon von den fcl Datanbankstrukturen aus so.

Edit: Jetzt hab ichs gesehn vieleicht ist Fields.DataSize nicht richtig implementiert.
mit .FieldDefs.Size gehts wunderbar. DataSize kannte ich vorher gar nicht.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Halvar
Beiträge: 58
Registriert: So 16. Mär 2008, 23:40
OS, Lazarus, FPC: Debian Lenny (L 0.9.28-2 FPC 2.2.4)
CPU-Target: 64Bit
Wohnort: Brake/Unterweser

Beitrag von Halvar »

Christian hat geschrieben:Ich hab mich sogar ziemlich viel damit beschäftigt, brauchte allerdings nie die feldgrössen nach dem anlegen einer Tabelle. Wie auch immer ich hab eben mal schnell eine tabelle im lazarus geöffnet und siehe da, dort werden die feldgrössen korrekt angezeigt der fehler liegt also definitiv nicht bei TDbf.
Mit den Datenbanktools wird schon alles richtig gespeichert, nur ich schreibe ein Tool, wo man Dbf-Dateien erstellen oder ggf. die Tabellenstruktur verändern kann.
Hier mal ein Link:
http://www.clicketyclick.dk/databases/xbase/format/index.html
Christian hat geschrieben:Es spielt auch keine Rolle wie Daten intern in der Datenbank gespeichert werden ein ftInteger Feld hat immer Grösse 0 zu haben denn die Länge ist durch den feldtyp vorgegeben. Da dürfte TDbf gar keinen Einfluss drauf haben das ist schon von den fcl Datanbankstrukturen aus so.
Es spielt definitiv eine Rolle! Gemäß Dbf-Spezifikation ist die Größe beim Feldtyp "N" zwischen 1 und 18 bei D3 bis D5 und FoxBase, zwischen 1 und 20 bei FoxPro und Clipper. Die Daten werden nicht Binär, sondern im Ascii-Format, gespeichert.
Christian hat geschrieben:Edit: Jetzt hab ichs gesehn vieleicht ist Fields.DataSize nicht richtig implementiert.
mit .FieldDefs.Size gehts wunderbar. DataSize kannte ich vorher gar nicht.

Ich habe es mit .FieldDefs.Size probiert. Leider kommt als Feldgröße wieder nur NULL raus.

Wenn es mit TDbf nicht gehen sollte, so werde ich kurzerhand eine eigene Unit erstellen. Komplett mit Indexverwaltung.
Lieber wäre es mir aber, ich könnte das vorhandene nutzen.

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Ich habs vorhin mit den aktuellen Lazarus/Fpc Versionen probiert und es geht über die Fielddefs, definitiv.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Halvar
Beiträge: 58
Registriert: So 16. Mär 2008, 23:40
OS, Lazarus, FPC: Debian Lenny (L 0.9.28-2 FPC 2.2.4)
CPU-Target: 64Bit
Wohnort: Brake/Unterweser

Beitrag von Halvar »

ICh nutze 0.9.24 und die passende FPC-Version. Mit welchen hast du es probiert?
Das Leben ist wie eine Hühnerleiter - kurz und beschissen

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

fpc 2.2.1 + lazarus 0.9.25 (ich denke aber nicth das die lazarus version damit was zu tun hat) und zur 0.9.24 passen alle fpc versionen > 1.9.x "passende fpc version" ist also nicht sehr aussagekräftig.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Antworten