[delphi] record naar string

Pagina: 1
Acties:

  • FendtVario
  • Registratie: Januari 2002
  • Laatst online: 12-05-2025

FendtVario

The leader drives Vario!

Topicstarter
Ik ben een netwerkapplicatie aan het ontwikkelen waarbij ik aan de serverkant een aantal records heb. Deze moeten naar de client, ik kan de records wel naar netwerkstream schrijven maar er hoort nog een procedure voor.

Is er een manier waarop ik een record als string kan aanbieden door een stukje geheugen te lezen of iets in die geest? In System.pas zit een functie _WriteRec, daarin is een hoop assembler omgenomen en daar wou ik maar afblijven. Maar misschien is deze code wel te herschrijven om een string te krijgen.

Iemand een oplossing misschien. In het record zitten ook zelf gedefinieerde type als:

Delphi:
1
2
type
   TSeason = (sSpring, sSummer, sAutumn, sWinter);

www.fendt.com | Nikon D7100 | PS5


  • jvdmeer
  • Registratie: April 2000
  • Laatst online: 16:45
Volgens mij moet je iets kunnen met de volgende termen: BlockWrite en SizeOf.

Bijvoorbeeld:
Geschreven:=BlockWrite(File, [variable], SizeOf([Variabele]))

en dan kan je lezen met:
BlockRead(File, [variable], SizeOf([Variabele]), Gelezen)

Doe dit geheel uit m'n hoofd, dus er kan een syntax fout in zitten.

  • FendtVario
  • Registratie: Januari 2002
  • Laatst online: 12-05-2025

FendtVario

The leader drives Vario!

Topicstarter
BlockRead en BlockWrite worden gebruikt bij het lezen van bestanden, als ik eerst het record in een stream of bestand moet schrijven en daarna weer lezen mis ik een hoop performance. Door het gebruik van een netwerk is de applicatie al niet al te snel dus ik wou eigenlijk een directe conversie.

www.fendt.com | Nikon D7100 | PS5


Verwijderd

Ik heb zoiets ooit gebruikt in een java netwerk applicatie. Daarbij maakte ik een vector aan met de losse waarden en die over een stream sturen. Zoiets moet met Delphi ook kunnen mbv de TObjectlist

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Je kan niet direct een record omzetten naar een string, maar je kan via TCP/IP sockets ook gewoon binaire data sturen.

Een enumiratie (jouw TSeason ) is gewoon een getal en kan dus dmv Typecasting van en naar een integer getypecast worden. Of het kan ook naar een string als je wilt
Delphi:
1
Result := GetEnumName(TypeInfo(TSeason), Ord(SeasonValue));

We adore chaos because we like to restore order - M.C. Escher


  • MisterE
  • Registratie: April 2002
  • Laatst online: 25-07 17:46
als ik je goed begrijp??

Dan zul je een functie daarvoor moetne maken, je kan een ordinale waarde niet automatisch laten omzetten. Delphi ziet het gewoon als constanten (0,1,2)

dus het word zoiets als dit:


function (input: TSeason): String;
begin
Case input of
sSpring : result := 'Spring';
sSummer: result := 'Summer';
//etc
end;

Maar het kan zijn dat ik je vraag niet goed begrijp :?

  • FendtVario
  • Registratie: Januari 2002
  • Laatst online: 12-05-2025

FendtVario

The leader drives Vario!

Topicstarter
MisterE schreef op 09 January 2003 @ 23:07:
als ik je goed begrijp??

Dan zul je een functie daarvoor moetne maken, je kan een ordinale waarde niet automatisch laten omzetten. Delphi ziet het gewoon als constanten (0,1,2)
dat doe ik nu ja, ik heb een functie RecordToString en StringToRecord, maar ik wil het altijd beter en sneller hebben dus vandaar deze vraag.

En GetEnumName is een leuke functie zei het dat dit ik hier nog ziet met Delphi 6 en GetEnumName pas in Delphi 7 is opgenomen.

www.fendt.com | Nikon D7100 | PS5


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

FendtVario schreef op 09 January 2003 @ 23:38:
dat doe ik nu ja, ik heb een functie RecordToString en StringToRecord, maar ik wil het altijd beter en sneller hebben dus vandaar deze vraag.

En GetEnumName is een leuke functie zei het dat dit ik hier nog ziet met Delphi 6 en GetEnumName pas in Delphi 7 is opgenomen.
Zoals ik al zei kan dat met
Delphi:
1
2
3
4
5
6
7
8
var Str: String;
      Season: TSeason;
begin
  Season := sSpring;

  Str := IntToStr(Integer(Season));  // Heen...
  Season := TSeason(StrToIntDef(Str, 0));  // ...en weer teug
end;

of mbv de GetEnumName en GetEnumValue in de typinfo (zonder e dus) unit. Deze zit al sinds mensenheugenis in Delphi. Het is alleen niet gedocumenteerd.

We adore chaos because we like to restore order - M.C. Escher


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 18:04

Tomatoman

Fulltime prutser

FendtVario schreef op 09 januari 2003 @ 23:38:
dat doe ik nu ja, ik heb een functie RecordToString en StringToRecord, maar ik wil het altijd beter en sneller hebben dus vandaar deze vraag.
Dacht je werkelijk dat een aanpassing ook maar iets aan snelheid zou opleveren? Een paar extra clock cycles aan rekenwerk vormen echt niet de bottleneck. Die wordt gevormd door de snelheid van je netwerkverbinding.

Een goede grap mag vrienden kosten.


  • FendtVario
  • Registratie: Januari 2002
  • Laatst online: 12-05-2025

FendtVario

The leader drives Vario!

Topicstarter
Ik snap ook wel dat de bottleneck in het netwerk zit, maar op de manier waarop ik nu een record omzet naar een string gebruik ik een aantal case en if_then_else structuren. En ik had gehoopt dat een directe conversie kleiner zou zijn dan mijn manier. Toch nog een beetje winst halen dus.

www.fendt.com | Nikon D7100 | PS5


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 25-08 22:13
Een voorbeeld volgt. Belangrijk is een paar dingen. Als je een dynamic array gebruikt of een string (AnsiString, WideString) in je record heb je een 'probleem' want dat zijn nl pointers. Je moet dan gaan marshallen ( is niet moeilijk maar je moet er wat code voor schrijven). Het voorbeeld gebruikt wel een string maar dan een static string (die dus maar 255 max mag zijn). Wat ook belangrijk is is dat je een packed record gebruikt zodat je later geen problemen hebt als je een andere delphi versie wil gebruiken of als iemand het met een andere compiler wil lezen

Groet

Martijn

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
StdCtrls;

type
TForm1 = class(TForm)
IdTCPClient1: TIdTCPClient;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

type

TMyRec = packed record
een : Integer;
twee : Integer;
aap : String[100];
end;

procedure TForm1.Button1Click(Sender: TObject);
var
R : TMyRec;
T : TMyRec;
S : String;
begin

R.een := 1;
R.twee := 2;
R.aap := 'aap';

T.een := 0;
T.twee := 0;
T.aap := '';

SetLength( S, Sizeof( TMyRec ) );
Move( R, PChar( S )^, Length( S ) );
(* S bevat nu de data van R *)
Move( PChar( S )^, T, Length( S ) );
(* T bevat nu de data van S dus van R *)
MessageDlg( Format( '%d, %d, %s', [ T.een, T.twee, T.aap ] )
, mtInformation, [mbOK], 0 );
end;

end.

  • FendtVario
  • Registratie: Januari 2002
  • Laatst online: 12-05-2025

FendtVario

The leader drives Vario!

Topicstarter
Ga het meteen ff proberen, ik gebruik alleen integers en eigen declaraties (zie eerste post) in het record. Van het packed record zie ik nog niet helemaal, ga er wel ff mee experimenteren.

Thnx

* FendtVario bookmarks this solution :)

www.fendt.com | Nikon D7100 | PS5


  • martijn_brinkers
  • Registratie: November 2001
  • Laatst online: 25-08 22:13
Als je niet packed gebruikt kan het zijn dat de complier extra bytes toevoegd om te zorgen dat je record altijd op bepaald geheugen grenzen staat (boundaries). De rede hiervoor is is dat het (evt) sneller gaat wbt geheugen access maar het nadeel is wel dat dat het per compiler anders kan zijn. Dat is dus niet wenselijk als je bijv. een uitwisseling wil doen met een andere programma. Het kan zelfs zijn hoor dat als je een nieuwe Delphi gaat gebruiken dat het dan anders is. Ditzelfde effect heb je ook bij C, C++ compilers waarin je dan moet aangeven op welke word boudary je struct staat.
Pagina: 1