Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi VST Stream.Write mit Delphi2010 (https://www.delphipraxis.net/154898-vst-stream-write-mit-delphi2010.html)

Berni68 29. Sep 2010 20:59

VST Stream.Write mit Delphi2010
 
Hallo,

zum speichern/laden von strings eines Virtual String Trees schreibe ich im Ereignis:
.VSTSaveNode(Sender: TBaseVirtualTree; Node: PVirtualNode; Stream: TStream)
Delphi-Quellcode:
    procedure SchreibeString(s:string);
    var
      L: integer;
    begin
      //L:= Length(s); Stream.Write(L, SizeOf(s)); Stream.Write(PChar(s)^, L); {geht in Delphi5}
      L:= Length(s);
      Stream.Write(L, SizeOf(s));
      Stream.Write(PWideChar(s)^, L);
    end;
.VSTLoadNode(Sender: TBaseVirtualTree; Node: PVirtualNode; Stream: TStream);
Delphi-Quellcode:
    procedure LeseString(var s:string);
    var
      L: integer;
    begin
      //Stream.Read(L, SizeOf(s)); SetLength(s, L); Stream.Read(PChar(s)^, L); {geht in Delphi5}
      Stream.Read(L, SizeOf(s));
      SetLength(s, L);
      Stream.Read(PWideChar(s)^, L);
    end;
In Delphi2010 klappt das so nicht mehr.
Die Änderung PChar -> PWideChar reicht wohl nicht, was ist hier falsch?

xZise 29. Sep 2010 22:40

AW: VST Stream.Write mit Delphi2010
 
Das Hauptproblem ist das ein Unicode Char zwei Byte groß ist. Das heißt beim, speichern musst du doppelt so viele Bytes schreiben wie sonst.

Das heißt wenn du den Text liest oder schreibst dann die Länge mit SizeOf(Char). Wenn du sicher gehen willst das es auch noch unter den Vorgänger geht dann nimm WideChar.

Falls es das nicht ist dann habe ich den Problem falsch erraten und du solltest genauer sagen was nicht funktioniert.

MfG
Fabian

Berni68 30. Sep 2010 18:59

AW: VST Stream.Write mit Delphi2010
 
das mit der Länge war schon mein Problem.
Ich hab dann mal bei Lazarus geschaut und da folgendes gefunden:
stream.WriteAnsiString(s)
Fehlt leider in Delphi!

allerdings konnte ich das Problem folgendermaßen lösen
(Miniprogramm: Formular mit 2 Buttons):
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    ButtonSchreiben: TButton;
    ButtonLesen: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure ButtonSchreibenClick(Sender: TObject);
    procedure ButtonLesenClick(Sender: TObject);
  private
    s1,s2: string;
    stream: TMemoryStream;
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  stream:= TMemoryStream.Create;
  s1:= '1234567890'+#13+'zeile2 äöü';
  s2:= 'x';
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  stream.Free;
end;

procedure TForm1.ButtonSchreibenClick(Sender: TObject);
var
  L: integer;
begin
  //stream.WriteAnsiString(s1); // gibt es in Lazarus und ist folgendermaßen umgesetzt:
{ L:= Length(s1);
  Stream.Write(L, SizeOf(L));
  Stream.Write(Pointer(s1)^, L);}

  L:= Length(s1);
  Stream.Write(L, SizeOf(L));
  Stream.Write(PChar(s1)^, L*SizeOf(Char));
end;

procedure TForm1.ButtonLesenClick(Sender: TObject);
var
  L: integer;
//  P: PByte;
begin
  stream.Position:= 0;
//  h:= stream.ReadAnsiString; // gibt es in Lazarus und ist folgendermaßen umgesetzt:
{ Stream.Read(L,SizeOf(L));
  SetLength(s2, L);
  if L>0 then begin
    Stream.Read(Pointer(s2)^, L);
    P:= Pointer(s2) + L;  // <- geht nicht in Delphi (in Lazarus aber schon)
    p^:=0;
  end; }

  Stream.Read(L, SizeOf(L));
  SetLength(s2, L);
  Stream.Read(PChar(s2)^, L*SizeOf(Char));

  showmessage('#' +s2 + '#');
end;

end.
Allerdings verstehe ich nicht, daß sich die FreePascal Lösung nicht in Delphi kompilieren läßt. (PByte + integer) In Lazarus geht das ohne Problem.
Allerdings ist es jetzt auch in Delphi so, daß der String den man reinschreibt auch wieder rauskommt.
Vielleicht kann es ja mal jemand brauchen.

xZise 30. Sep 2010 19:10

AW: VST Stream.Write mit Delphi2010
 
Ich weiß jetzt gerade nicht, wieso es nicht funktioniert, aber das ist doch das gleiche:
Delphi-Quellcode:
var
  s : string;
begin
  s := '....';
  s := s + #0;
Oder halt:
Delphi-Quellcode:
var
  p : PChar;
begin
  p := PChar(s);
MfG
Fabian

Berni68 30. Sep 2010 19:24

AW: VST Stream.Write mit Delphi2010
 
Die Zeile

Delphi-Quellcode:
P:= Pointer(s2) + L;

quittiert Delphi mit:
[DCC Fehler] Unit1.pas(67): E2015 Operator ist auf diesen Operandentyp nicht anwendbar

xZise 30. Sep 2010 19:30

AW: VST Stream.Write mit Delphi2010
 
Moin,
wieso soll dann ein PByte raus kommen? Müsste nicht ein PChar herauskommen? Beziehungsweise es kommt ein Pointer raus.

[edit]Gerade getestet, scheint nicht zu gehen. Warum weiß ich nicht, bin auch net so der Pointerspezi. (und ist btw eine andere Frage, müsste also streng genommen in einen anderen Thread)[/edit]

MfG
Fabian

Berni68 30. Sep 2010 19:38

AW: VST Stream.Write mit Delphi2010
 
Ich verstehe das auch nicht, aber in FreePascal funktioniert das ohne Probleme.

Aber wie dem auch sein, mein eigentliches Problem ist ja gelöst.:-D

xZise 30. Sep 2010 20:44

AW: VST Stream.Write mit Delphi2010
 
Allerdings könnte es problematisch werden, wenn ein Zeichen mehrere Bytes beansprucht! Ähnlich wie beim schreiben oder lesen. Da würde ich halt immer ein #0 anhängen. Damit funktioniert es mit ASCII, UTF16, UTF32 aber auch mit UTF8, wo ja ein Zeichen nicht die gleiche Länge haben müssen.

MfG
Fabian


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:26 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