In dBASE - Dateien, die von anderen Programmen erstellt wurden, sind in Delphi die numerische Felder scheinbar leer. In dBASE III o.ä. Programmen werden sie aber angezeigt.
Hintergrund: In dBASE - Dateien werden Zahlen als Zeichenkette mit den entsprechenden Dezimalstellen abgelegt. Dabei werden nicht benötigte Stellen linksbündig mit Leerzeichen aufgefüllt. (z.B. 2.54 --> xxx2.54 {x = Leerzeichen}). Speichert das Fremdprogramm die Zahl aber als xx2.54x, kann Delphi damit nichts anfangen, die Felder sind scheinbar leer.
Hilfe Solche Dateien müssen konvertiert werden.
Folgende Prozedur korrigiert die Datei. Dabei wird zur Sicherheit erst abgespeichert, wenn die Routine fehlerfrei durchlaufen wurde.
type
TDBFKopf = packed record
Version: Byte;
Zugriff: array[0..2] of char;
RecCount: LongInt;
HaederSize: SmallInt;
RecordSize: SmallInt;
Dummy: array[0..19] of Char;
end;
TDBFFeld = packed record
Name: array[0..10] of Char;
Typ: Char;
Adress: LongInt;
Size: byte;
Decimal: byte;
Dummy: array[0..13] of Char;
end;
TDbfFelder = array[0..255] of TDBFFeld;
procedure DBF_Reparieren(TableName: TFileName);
var
Ziel, Quelle : TFileStream;
FieldCount : integer;
Kopf : TDBFKopf;
Felder : ^TDBFFelder;
z, i : Integer;
c : Char;
Daten : PChar;
isKorr : boolean;
procedure Korr_Datensatz;
var
s : ShortString;
z, l : integer;
falsch : boolean;
begin
for z := 0 to FieldCount - 1 do begin
s := '';
for l := 0 to Felder^[z].Size - 1 do
s := s + Daten[Felder^[z].Adress + l];
Falsch := false;
case Felder^[z].Typ of
'N': if (trim(s) <> '') and (s <> TrimRight(s)) then begin
s := LFill(TrimRight(s), Felder^[z].Size);
Falsch := true;
end;
end;
if Falsch then begin
isKorr := true;
for l := 0 to Felder^[z].Size - 1 do
Daten[Felder^[z].Adress + l] := s[l + 1];
end;
end;
end;
begin
isKorr := false;
Quelle := TFileStream.Create(ChangeFileExt(TableName, '.DBF'),
fmOpenRead);
Ziel := TFileStream.Create(ChangeFileExt(TableName, '.$$$'),
fmCreate);
try
Quelle.ReadBuffer(Kopf, SizeOf(Kopf));
FieldCount := (Kopf.HaederSize - 1) div 32 - 1;
GetMem(Felder, FieldCount * SizeOf(TDbfFeld));
GetMem(Daten, Kopf.RecordSize);
try
Quelle.ReadBuffer(Felder^, FieldCount * SizeOf(TDbfFeld));
Quelle.ReadBuffer(c, SizeOf(c));
if c <> #$0D then
// Kopf richtig eingelesen ?
raise Exception.Create('Kopf ist Falsch');
// Dateikopf ist o.k --> zurückspeichern
Ziel.WriteBuffer(Kopf, SizeOf(Kopf));
Ziel.WriteBuffer(Felder^, FieldCount * SizeOf(TDbfFeld));
Ziel.WriteBuffer(c, SizeOf(c));
i := 1;
// Löschflag übergehen
for z := 0 to FieldCount - 1 do begin
Felder^[z].Adress := i;
i := i + Felder^[z].Size;
end;
if i <> Kopf.RecordSize then
// Felddefinitionen richtig ?
raise Exception.Create('Feldgröße ist falsch');
for z := 0 to Kopf.RecCount - 1 do begin
Quelle.ReadBuffer(Daten^, Kopf.RecordSize);
Korr_Datensatz;
Ziel.WriteBuffer(Daten^, Kopf.RecordSize);
end;
Quelle.Read(c, SizeOf(c));
if c <> #$1A then
// Endekennzeichen ?
raise Exception.Create('Länge der Datei ist falsch');
Ziel.WriteBuffer(c, SizeOf(c));
finally
FreeMem(Daten);
FreeMem(Felder);
end;
finally
Quelle.Free;
Ziel.Free;
end;
if isKorr then begin
if Sysutils.DeleteFile(ChangeFileExt(TableName, '.dbf')) then
RenameFile(ChangeFileExt(TableName, '.$$$'),
ChangeFileExt(TableName, '.DBF'));
end;
SysUtils.DeleteFile(ChangeFileExt(TableName, '.$$$'));
end;
|