AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi Stringfield in Datenbank; EIN Byte ÄNDERN
Thema durchsuchen
Ansicht
Themen-Optionen

Stringfield in Datenbank; EIN Byte ÄNDERN

Ein Thema von Kurt56 · begonnen am 26. Sep 2007 · letzter Beitrag vom 27. Sep 2007
Antwort Antwort
Benutzerbild von Kurt56
Kurt56

Registriert seit: 6. Apr 2005
Ort: Wedemark
47 Beiträge
 
Delphi XE8 Professional
 
#1

Stringfield in Datenbank; EIN Byte ÄNDERN

  Alt 26. Sep 2007, 12:57
Datenbank: Perversive (BTrieve) • Version: 8 • Zugriff über: ODBC
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:
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]);
programmiere, dann wird die Zahl 30000 in X[1]=30h; X[2]=75h; X[3]=00h und X[4]=00h umgewandelt,
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:
table1Anzahl.Value[1]:=char(x[1]); table1Anzahl.Value[2]:=char(x[2]);
table1Anzahl.Value[1]:=char(x[3]); table1Anzahl.Value[2]:=char(x[4]);
geht natürlich nicht.


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?
Kurt
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#2

Re: Stringfield in Datenbank; EIN Byte ÄNDERN

  Alt 26. Sep 2007, 13:48
Deine Vorgehensweise gefällt mir gar nicht; zu umständlich.
Zunächst wird ein Varianter Record definiert:
Delphi-Quellcode:
type
   T32BitCharField = record
      case Integer of
         0:
          (LongValue:Longint);
         1:
          (bytes: array[0..3] of char);
   end;
Damit kann man zwischen den verschiedenen Darstellungen wechseln:
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;
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von Kurt56
Kurt56

Registriert seit: 6. Apr 2005
Ort: Wedemark
47 Beiträge
 
Delphi XE8 Professional
 
#3

Re: Stringfield in Datenbank; EIN Byte ÄNDERN

  Alt 26. Sep 2007, 14:34
Zitat von shmia:
Deine Vorgehensweise gefällt mir gar nicht; zu umständlich.
Zunächst wird ein Varianter Record definiert:
Delphi-Quellcode:
type
   T32BitCharField = record
      case Integer of
         0:
          (LongValue:Longint);
         1:
          (bytes: array[0..3] of char);
   end;
Damit kann man zwischen den verschiedenen Darstellungen wechseln:
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;
Leider wird daraus dann nicht 30 75 00 00, sondern 97 30 30 30 hex ( 'ù000' )

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.
Kurt
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#4

Re: Stringfield in Datenbank; EIN Byte ÄNDERN

  Alt 26. Sep 2007, 14:38
Zitat:
s := adstableAnzahl.AsString; // Feld auslesen Datenbankfeld Integer 30000 => s: ergibt s:= '30000'
Achso, dass bedeutet dass du das Feld direkt wie es ist auslesen kannst.
Damit erübrigt sich doch sämtlicher Aufwand.
Delphi-Quellcode:
var
   anzahl:integer;
begin
   anzahl := adstableAnzahl.AsInteger;
   anzahl := anzahl + 100;
   adstableAnzahl.AsInteger := anzahl;
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von Kurt56
Kurt56

Registriert seit: 6. Apr 2005
Ort: Wedemark
47 Beiträge
 
Delphi XE8 Professional
 
#5

Re: Stringfield in Datenbank; EIN Byte ÄNDERN

  Alt 26. Sep 2007, 15:27
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

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.
Kurt
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#6

Re: Stringfield in Datenbank; EIN Byte ÄNDERN

  Alt 26. Sep 2007, 15:57
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:
adstable.FieldByName('Anzahl').SetData(@s[1], True); So kann man die Daten direkt setzen, ohne dass die interne Methode DataConvert() aufgerufen wird.
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von Kurt56
Kurt56

Registriert seit: 6. Apr 2005
Ort: Wedemark
47 Beiträge
 
Delphi XE8 Professional
 
#7

Re: Stringfield in Datenbank; EIN Byte ÄNDERN

  Alt 26. Sep 2007, 17:59
Zitat von shmia:
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:
adstable.FieldByName('Anzahl').SetData(@s[1], True); So kann man die Daten direkt setzen, ohne dass die interne Methode DataConvert() aufgerufen wird.
Ja, genau das mit der Formatierung ist mein Problem.

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:
s:=char(x[1])+char(x[2])+char(x[3])+char(x[4]);
adstable1.FieldByName('Anzahl').SetData(@s, True);
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.

Kannst du mir sagen, was ich falsch mache ?
Kurt
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#8

Re: Stringfield in Datenbank; EIN Byte ÄNDERN

  Alt 26. Sep 2007, 19:42
Zitat von Kurt56:
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.
Kannst du mir sagen, was ich falsch mache ?
Vielleicht machst du gar nix falsch, nur der Treiber hat seine Finger dazwischen.
Wie wird denn der Datentyp gemeldet ?
ShowMessage(FieldTypeNames[adstable.FieldByName('Anzahl').DataType]); Es gäbe da noch die Möglichkeit, dass du persistente Felder anlegst.
Dein Spezialfeld müsste dann zu einem TBytesField geändert werden damit die VCL keinerlei Interpretationen vornimmt, sondern die Daten 1:1 durchreicht.
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von Kurt56
Kurt56

Registriert seit: 6. Apr 2005
Ort: Wedemark
47 Beiträge
 
Delphi XE8 Professional
 
#9

Re: Stringfield in Datenbank; EIN Byte ÄNDERN

  Alt 27. Sep 2007, 15:35
DataType ist "String".

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.

Kurt
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:10 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz