![]() |
Datenbank: Perversive (BTrieve) • Version: 8 • Zugriff über: ODBC
Stringfield in Datenbank; EIN Byte ÄNDERN
Ich habe eine Fremdanwendung, auf die ich zugreifen muß.
Es ist eine Datenbank (BTrieve), die ich auch bearbeiten kann. Soweit so gut. Aber der Kollege von einst hat ein Datenbankfeld definiert Character, 4 Byte lang in das er aber eine 4-Byte-Integerzahl BINÄR "hart" überschreibt. Dort steht dann 00 00 00 00 für Null, oder 30 75 00 00 für 30000 WENN ich nun
Delphi-Quellcode:
programmiere, dann wird die Zahl 30000 in X[1]=30h; X[2]=75h; X[3]=00h und X[4]=00h umgewandelt,
var x : array[1..4] of byte;
i, j : Integer; i:= adstableAnzahl.Value div 16777216; x[4]:=ord(i); j:= adstableAnzahl.Value mod 16777216; i:=j div 65536; x[3]:=ord(i); i:=j mod 65536; j:=i div 256; x[2]:=ord(j); j:=i mod 256; x[1]:=ord(j); table1Anzahl.Value:=char(x[1])+char(x[2])+char(x[3])+char(x[4]); aber, weil das Datenbankfeld ein 4-Byte Charakterfeld ist, werden nur das erste und zweite Byte übertragen, die 0-Byte werden (als Stringende) nicht mit "angesehen" und im Tabellenfeld steht dann: 03 75 20 20, also mit BLANK aufgefüllt. -------------------------------------- Wie kann ich auf die einzelnen BYTES des 4-Byte Stringfeldes zugreifen? (Zeiger vielleicht) Denn
Delphi-Quellcode:
geht natürlich nicht.
table1Anzahl.Value[1]:=char(x[1]); table1Anzahl.Value[2]:=char(x[2]);
table1Anzahl.Value[1]:=char(x[3]); table1Anzahl.Value[2]:=char(x[4]); Ich habe auch schon for i:= 1 to 4 do X[i] := x[i] xor 255; table1Anzahl.Value:=char(x[1])+char(x[2])+char(x[3])+char(x[4]); gemacht. Damit schreibt er natürlich 00h als FFh und alle 4 Byte werden gefüllt. ABER table1Anzahl.Value[4] := table1Anzahl.Value[4] xor #255; geht auch nicht. Mit IF kann man ein Byte ABFRAGEN (if table1Anzahl.Value[4] = #0 then ....) aber nicht schreiben. Kann mir jemand einen Tip geben, wie ich die Byte im String, in der Tabelle, beschreiben kann? |
Re: Stringfield in Datenbank; EIN Byte ÄNDERN
Deine Vorgehensweise gefällt mir gar nicht; zu umständlich.
Zunächst wird ein Varianter Record definiert:
Delphi-Quellcode:
Damit kann man zwischen den verschiedenen Darstellungen wechseln:
type
T32BitCharField = record case Integer of 0: (LongValue:Longint); 1: (bytes: array[0..3] of char); end;
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var x : T32BitCharField; s : string; begin s := adstableAnzahl.AsString; // Feld auslesen StrLCopy(x.bytes, Pchar(s), 4); // auf "x" kopieren // x wird verändert x.LongValue := x.LongValue + 100; SetString(s, x.bytes, 4); dstableAnzahl.AsString := s; // Feld zurückschreiben end; |
Re: Stringfield in Datenbank; EIN Byte ÄNDERN
Zitat:
Delphi-Quellcode:
s := adstableAnzahl.AsString; // Feld auslesen ______________ Datenbankfeld Integer 30000 => s: ergibt s:= '30000'
StrLCopy(x.bytes, Pchar(s), 4); // auf "x" kopieren__________ x wird zu ==> '3' '0' '0' '0' // x wird verändert x.LongValue := x.LongValue + 100;_____________________________ aus '30000' wird ==> 808464535 SetString(s, x.bytes, 4); ________umgewandelt in einen String 'ù0000' dstableAnzahl.AsString := s; // Feld zurückschreiben ________der dann in das Datenbankfeld geschreiben wird. |
Re: Stringfield in Datenbank; EIN Byte ÄNDERN
Zitat:
Damit erübrigt sich doch sämtlicher Aufwand.
Delphi-Quellcode:
var
anzahl:integer; begin anzahl := adstableAnzahl.AsInteger; anzahl := anzahl + 100; adstableAnzahl.AsInteger := anzahl; |
Re: Stringfield in Datenbank; EIN Byte ÄNDERN
Vielen Dank für deine Mühe,
aber, das hast du leider völlig mißverstanden. Der "Kollege" hatte vor vielen Jahren, in einer mir nicht bekannten Sprache, eine Datenbank mit BTrieve kreiert und dabei ein Datenbankfeld "vergewaltigt". SEIN Programm speichert in einem CHAR-Datenbankfeld mit 4 Byte eine ZAHL-GEPACKT. Aber nicht mal so einfach, sondern 1 ist 01 00 00 00 hex 30000 ist 30 75 00 00 hex das zu LESEN ist kein Problem, denn die Stringvariable liefert bei 1 = ein Byte mit 01 hex (die restlichen 3 Byte werden als Nul-String nicht gelesen) 30000 = 2 Byte mit 30 75 hex, die beiden restilechen Byte werden als Nul-String nicht gelesen. Leider muß ich auch zurückschreiben. Und wenn das Programm, mit dem wir sonst arbeiten (müssen) dort '3000' vorfindet (es sind nur 4 Character) oder 30hex 75hex 20hex=blank 20hex=blank ( 30 75 20 20 wird als 538.998.064 interpretiert.) Wir wollen aber nicht 538.998.064 Stück herstellen, sondern nur 30.000 Stück :roll: Deshalb hatte ich das ja auch so umständlich programmiert. Aber, wie ich das String-Feld in der Datenbank "überzeugen" soll, dass es alle 4 Byte (auch die mit NULL) annehmen soll, weis ich nicht. Bin schon recht verzweifelt. :wall: |
Re: Stringfield in Datenbank; EIN Byte ÄNDERN
Ich hab zwar jetzt nicht verstanden, weshalb im String s der Wert '3000' steht,
obwohl er eigentlich #$30#$75#$00#$00 sein müsste, aber egal. Beim Schreiben wird anscheinend mit Blanks aufgefüllt, das ist dein Hauptproblem. Dann versuch mal:
Delphi-Quellcode:
So kann man die Daten direkt setzen, ohne dass die interne Methode DataConvert() aufgerufen wird.
adstable.FieldByName('Anzahl').SetData(@s[1], True);
|
Re: Stringfield in Datenbank; EIN Byte ÄNDERN
Zitat:
Ich habe besagtes Array var x : array[1..4] of byte; s : string; X[1] ist #30 X[2] ist #75 X[3] und x[4] sind #0 Wenn ich
Delphi-Quellcode:
mache, dann habe ich immer noch nur eine length(adstable1anzahl.value) von 2 (nicht von 4) und es ist immer noch mit BLANK aufgefüllt.
s:=char(x[1])+char(x[2])+char(x[3])+char(x[4]);
adstable1.FieldByName('Anzahl').SetData(@s, True); Kannst du mir sagen, was ich falsch mache ? |
Re: Stringfield in Datenbank; EIN Byte ÄNDERN
Zitat:
Wie wird denn der Datentyp gemeldet ?
Delphi-Quellcode:
Es gäbe da noch die Möglichkeit, dass du persistente Felder anlegst.
ShowMessage(FieldTypeNames[adstable.FieldByName('Anzahl').DataType]);
Dein Spezialfeld müsste dann zu einem TBytesField geändert werden damit die VCL keinerlei Interpretationen vornimmt, sondern die Daten 1:1 durchreicht. |
Re: Stringfield in Datenbank; EIN Byte ÄNDERN
DataType ist "String". :pale:
Gibt es irgendeine Möglichkeit, die Physikalische Adresse des Speicherbereiches "adstable1Anzahl.value" zu bekommen? Also jene Speicherstelle, auf der diese verflixten 4 Byte stehen? Dann könnte ich ja per Assembler "hart" diese Bytes löschen. :gruebel: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:29 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz