Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi WideString -> TStream? (https://www.delphipraxis.net/97955-widestring-tstream.html)

blackdrake 19. Aug 2007 17:47


WideString -> TStream?
 
Hallo.

Ich möchte einen String im WideString-Format (bei ANSI 00h zwischen jedem Zeichen) in einen TFileStream speichern. Vorher wandle ich ein String in WideString um.

Delphi-Quellcode:
public
  tempstream: TStream;

procedure Write(const Value; Size: Integer);
begin
   mainform.tempstream.WriteBuffer(Value, Size);
end;

procedure WriteRaw(const Value: Binary);
begin
  Write(Value[1], Length(Value));
end;

var
  ws: widestring;
begin
  ws := mainform.edt_vle1.text;
  WriteRaw(ws+#00#00);
end;
Das Ergebnis, das man im Hexeditor betrachten kann, ist jedoch:

abcde[NULL][NULL]

Wieso hat die String -> WideString konvertierung nicht funktioniert?

Da mein Projekt OpenSource ist, möchte ich keine fremden, kostenpflichtigen Komponenten verwenden. Der Benutzer soll mit frei erhältlichen Komponenten oder den Borland-VCLs das Projekt öffnen können. Daher muss ich bis 2008 warten, bis Borland vollen Unicode-Support für die VCLs bietet. Solange wandle ich einfach die Strings in WideStrings um. Das Dateiformat will ich aber bereits Unicode-Ready machen.

Gruß
blackdrake

sirius 19. Aug 2007 18:08

Re: WideString -> TStream?
 
Was ist denn binary?


Edit: Derzeit kannst du einen Widestring z.B. so speichern:
Delphi-Quellcode:
var ws:widestring;
begin
  ws:=edit1.text;
  stream.Write(ws[1],sizeof(WideChar)*(length(ws)+1));
end;
Aber ob das noch Betsand hat (besonders das "length+1"), wenn mal völlig auf Unicode umgestellt wird.... :stupid:

Edit2: Natürlich "ws:widestring" :mrgreen:
Edit3: Ok, ich glaube hier sind noch tausend fehler drinn :drunken:

blackdrake 19. Aug 2007 18:32

Re: WideString -> TStream?
 
Hallo.

Danke für die Antwort

Delphi-Quellcode:
public
  tempstream: TStream;

procedure Write(const Value; Size: Integer);
begin
  mainform.tempstream.WriteBuffer(Value, Size);
end;

procedure WriteWideString(const Value: WideString);
begin
  Write(Value[1], sizeof(Char)*(length(Value)+1));
end;

var
  ws: widestring;
begin
  ws := mainform.edt_vle1.text;
  WriteWideString(ws+#00#00);
end;
Funktioniert leider nicht. In der Ausgabedatei steht weiterhin abcd[NULL][NULL], als wäre es ein AnsiString. :roll:

PS: Binary gibts übrigens bei DEC von Hagen Reddmann. Konnte ich jetzt bei dieser WideString lösung steichen.
`
Edit: Fehler besteht sowohl bei Write() als auch bei WriteBuffer() von TStream.

Gruß
Daniel Marschall

Muetze1 19. Aug 2007 18:36

Re: WideString -> TStream?
 
Hinweis: Beachte das Zeichen Index 1 ungültig ist bei einer Stringlänge von 0!

sirius 19. Aug 2007 18:36

Re: WideString -> TStream?
 
:oops: Sorry, ich hatte oben noch das sizeof(char) zu sizeof(widechar) geändert.
Wobei ich mich gerade frage, warum du einen ansistring gespeichert bekommst und (mit dem Fehler) nicht nur die erste Hälfte des widestrings :gruebel:

blackdrake 19. Aug 2007 18:41

Re: WideString -> TStream?
 
Hallo. sizeof(char) hab ich zu sizeof(widechar) gemacht und erhalte genau das selbe Ergebnis. Irgendwas ist hier komisch. Wieso funktioniert die String -> WideString umwandlung nicht? Funktioniert bei euch dieses Script?

sirius 19. Aug 2007 18:51

Re: WideString -> TStream?
 
Zitat:

Zitat von Muetze1
Hinweis: Beachte das Zeichen Index 1 ungültig ist bei einer Stringlänge von 0!

Man sollte es sich nicht angewöhnen, aber in dem Fall (widestring zu PWideChar) würde es klappen.


btw: @blackdrake. In meinem Memorystream landet genau das, was du willst.

blackdrake 19. Aug 2007 18:56

Re: WideString -> TStream?
 
Geht denn eine WideString Speicherung nicht auch mit FileStream?

sirius 19. Aug 2007 19:03

Re: WideString -> TStream?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Klappt bei mir genauso (ich habs nur erst mit Tmemorystream gemacht, weil ichs da einfacher überprüfen kann).

Code (in Anlehnung an deinen):
Delphi-Quellcode:
type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    x:tfilestream;
    procedure write(const buffer;size:integer);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.write(const buffer;size:integer);
begin
  x.Writebuffer(buffer,size);
end;

procedure TForm1.Button1Click(Sender: TObject);
var ws:widestring;
begin
  ws:=edit1.text;
  x:=tfilestream.Create('T:\test.txt',fmcreate);
  Write(ws[1],sizeof(wideChar)*(length(ws)+1));
  x.free;
end;

end.
Ergebnis siehe Anhang.

blackdrake 19. Aug 2007 19:26

Re: WideString -> TStream?
 
Hallo.

Danke für euere Hilfe. Seltsamerweiße liegt es daran, dass ich Write(...) in eine Prozedur ausgelagert habe. Sobald ich es in eine Funktion auslagere, schreibt er einen AnsiString in die Datei. Die Auslagerung ist aber nicht so wichtig.

Jetzt muss ich nur noch abwarten bis Borland 2034 endlich Unicode-Kompatible VCLs fertigstellt, damit die Stelle im Dateiformat Sinn ergibt.

Was ist jetzt eigentlich mit dem [1] und einem leeren String? Mein PC ist nicht in einer atomaren Explosion untergegangen, als ich die Editbox geleert und die Aktion ausgeführt habe.

Gruß
blackdrake

sirius 19. Aug 2007 19:42

Re: WideString -> TStream?
 
Zitat:

Was ist jetzt eigentlich mit dem [1] und einem leeren String? Mein PC ist nicht in einer atomaren Explosion untergegangen, als ich die Editbox geleert und die Aktion ausgeführt habe.
Bei dir gibt es durch das ws+#0#0 sowieso keine Probleme, da dein String damit niemals leer ist. Ergo: Brauchst du den Kommentar nicht beachten.

Falls du aber mal einen string nicht konstant erweiterst, bevor du auf eine Element zugreifst:
Wenn du das mit einem ansistring versuchst, dann greift das Programm bei einem leeren string auf Adresse $0000000 zu und es gibt eine AV.
Bei WideString ist das (derzeit) aber wiederum völlig anders. Delphi macht aus dem Widestring einen PWideChar. Und wenn der widestring leer ist, dann gibt diese Funktion als Ergebnis einen gültigen Zeiger auf #00#00 im Datensegment zurück. Dadurch gibt es keine AV. Allerdings sollte man sich auf so etwas nicht verlassen (man weis ja nie was der Compiler morgen macht) und lieber vorher abfragen, ob ws ein Leerstring ist. Du kannst auch gleich statt "value[1]" PWideChar(Value) nehmen. Dann wärst du auf der sicheren Seite, wenn nicht dieses Problem dir dazwischen funkt.

PS: Ich frage mich grad, ob der Compiler bei WS+#0#0 2 Bytes oder 4 Bytes anhängt :gruebel:
Edit: Bei mir sind es vier.

Muetze1 19. Aug 2007 21:19

Re: WideString -> TStream?
 
Zitat:

Zitat von sirius
Wenn du das mit einem ansistring versuchst, dann greift das Programm bei einem leeren string auf Adresse $0000000 zu und es gibt eine AV.

Bei eingeschaltetem RangeCheck wird in beiden Fällen zuvor eine ERangeCheckException ausgelöst. Somit sollte man sich sowas überhaupt nicht angewöhnen, weil sonst läuft das Programm nur einwandfrei bei bestimmten Compilereinstellungen.

blackdrake 19. Aug 2007 21:41

Re: WideString -> TStream?
 
Hallo.

@Mutze1: Wie sollte man den Code anders schreiben, damit er mit allen Compilereinstellungen funktioniert und sauber ist?

Kann mir jemand erklären, wieso eigentlich bei der Auslagerung der Write()-Funktion ein ANSI String anstelle eines WideStrings geschrieben wird? Ist eigentlich ein komisches Phänomen.

Gruß
blackdrake

DGL-luke 19. Aug 2007 21:53

Re: WideString -> TStream?
 
Zitat:

Zitat von sirius
Du kannst auch gleich statt "value[1]" PWideChar(Value) nehmen.


blackdrake 19. Aug 2007 22:02

Re: WideString -> TStream?
 
Danke, hatte ich übersehen. Leider funktioniert es dann nicht mehr.

Folgender Code:

Delphi-Quellcode:
public
  x: tfilestream;

procedure TForm1.write(const buffer;size:integer);
begin
  x.Writebuffer(buffer,size);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ws: widestring;
  pwc: pwidechar;
begin
  ws:=edit1.text;
  x:=tfilestream.Create('c:\test.txt',fmcreate);
  pwc := PWideChar(ws);
  Write(pwc, sizeof(wideChar)*(length(ws)+1));
  x.free;
end;
Erzeug nicht E[NULL]d[NULL]i[NULL]t[NULL]1[NULL][NULL], sondern "dd\".

Gruß
blackdrake

Muetze1 19. Aug 2007 22:07

Re: WideString -> TStream?
 
Delphi-Quellcode:
Write(pwc^, sizeof(wideChar)*(length(ws)+1));
Beachte das ^...

blackdrake 19. Aug 2007 22:08

Re: WideString -> TStream?
 
Vielen Dank :)


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