Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi WideString in Stream speichern - Wie? (https://www.delphipraxis.net/52947-widestring-stream-speichern-wie.html)

SirThornberry 7. Sep 2005 11:27


WideString in Stream speichern - Wie?
 
Ich bin gerade dabei das ich einen WideString in einen Stream speichern will. Bei einem normalen String würde ich das so machen:
Delphi-Quellcode:
var LSize: Integer;
begin
  LSize := Length(NormalerString); //Länge des Strings ermitteln
  Stream.Write(LSize, SizeOf(LSize)); //Länge des Strings abspeichern (fürs Laden benötigt)
  Stream.Write(NormalerString[1], LSize); //String in Stream schreiben
bei einem WideString würde ich das jetzt so machen
Delphi-Quellcode:
var LSize: Integer;
begin
  LSize := Length(TheWideString) * 2; //Länge des Strings ermitteln
  Stream.Write(LSize, SizeOf(LSize)); //Länge des Strings abspeichern (fürs Laden benötigt)
  Stream.Write(TheWideString[1], LSize); //String in Stream schreiben
Mich stört jetzt bei dieser Variante das "*2" weil es ja irgendwann mal passieren kann das unter windows ein Zeischen eines WideStrings dann 4 Byte lang ist. Wie würde ihr das machen um die 2 nicht fest rein zu schreiben?
Ich hab schon überlegt zu schreiben
Delphi-Quellcode:
LSize := Length(TheWideString) * SizeOf(WideChar);
Wie würdet ihr das machen?

Olli 7. Sep 2005 12:01

Re: WideString in Stream speichern - Wie?
 
Sizeof ist der korrekte Weg. Übrigens wird das Windows nicht einfach so ändern, sondern vermutlich nur auf einer neuen Architektur. Und genaugenommen können auch UTF-16-Zeichen schon bis 4 Bytes lang sein (allerdings dann eben als Merhfachzeichen gespeichert).

Tyrael Y. 7. Sep 2005 12:07

Re: WideString in Stream speichern - Wie?
 
...SizeOf benutzt er ja schon ;)

das wichtige ist du solltest SizeOf(DatenTyp) machen und nicht
SizeOf(Variable)


Gruß

mael 7. Sep 2005 12:11

Re: WideString in Stream speichern - Wie?
 
SizeOf(WideChar);
würde ich anstatt der Konstanten 2 verwenden, einfach weil es klarer ist, 2 kann in einem komplexeren Algo verschiedene Gründe haben, und später fragt man sich was jetzt der genaue Grund war.

Das Windows 4-Byte große Unicode-Zeichen einführt ist mit 99%-iger Sicherheit ausgeschlossen, da es vom Speicher her totale Verschwendung bedeutet, ganz abgesehen davon, daß dies auch zu allen bisherigen Unicode-APIs inkompatibel wäre. Mit 2 Byte Zeichen kann man die Basic Multilingual Plane (BMP) direkt beschreiben wo im Prinzip alle wichtigen Zeichen drin sind, die Zeichen außerhalb der BMP setzten sich aus 2 WideChars (=4 Bytes) zusammen und bilden ein sogenanntes Surrogate-Pair.

Zu deinem Kode:
Da fehlt noch die Markierung ob es ein WideString oder ein AnsiString ist, dafür würde ich daher eine Markierung einführen. Oder mir die ganze Arbeit sparen und die von Delphi mitgelieferten Bordmittel verwenden:
TWriter bzw TReader bieten Methoden um eigentlich alle Datentypen in einen Stream zu speichern und wieder korrekt auszulesen:
z.B. TWriter.WriteString, TWriter.WriteWideString
TReader.ReadString, TReader.ReadWideString
Der Vorteil dabei ist, daß Unicode-strings platzsparend als UTF-8 gespeichert werden und man mit TReader.NextValue bestimmen kann welche Funktion aufzurufen ist.

Kleines Beispiel:
Delphi-Quellcode:
case Reader.NextValue of
  vaInt8, vaInt16, vaInt32:
    i := Reader.ReadInteger;
  vaExtended:
    f := Reader.ReadFloat;
  vaSingle:
    f := Reader.ReadSingle;
  vaCurrency:
    cur := Reader.ReadCurrency;
  vaDate:
    d := Reader.ReadDate;
  vaWString, vaUTF8String:
    WS := Reader.ReadWideString;
  vaString, vaLString:
    S := Reader.ReadString;
  // es gibt noch weiter ValueTypes  
end;
Umgekehrt geht das Schreiben, ist also relativ einfach.

Olli 7. Sep 2005 12:17

Re: WideString in Stream speichern - Wie?
 
Zitat:

Zitat von Tyrael Y.
...SizeOf benutzt er ja schon ;)

Er überlegte (lt. oben) es zu benutzen. Ich habe nur zugeraten, weil es die portablere und bessere Variante ist. Der Compiler macht sowieso in der EXE eine 2 draus. Wenn der Code aber mal in 10 Jahren mit Delphi.NET64 2016 für Win64 kompiliert wird, kann man das mit Sizeof() immernoch machen.

SirThornberry 7. Sep 2005 15:45

Re: WideString in Stream speichern - Wie?
 
@mael: vermerken ob es unicode oder ansicode ist fällt weg da die Komponente welchen den Source beinhaltet generell nur mit WideString arbeitet und somit auch nur diese gespeichert werden.

Ok, dann werd ich mit SizeOf das ganze machen und hoffen das microsoft wirklich bei den 2 Byte bleibt.

Olli 7. Sep 2005 15:57

Re: WideString in Stream speichern - Wie?
 
Zitat:

Zitat von SirThornberry
Ok, dann werd ich mit SizeOf das ganze machen und hoffen das microsoft wirklich bei den 2 Byte bleibt.

Nochmal:
Sizeof bringt dir hier "nur" den Vorteil, daß du es später auf einem anderen System kompilieren kannst, ohne daß der Code geändert werden muß. Denk mal logisch: MS kann nicht einfach alle *W()-APIs so modifiziern, daß die plötzliche andere Standards benutzen. Damit würden sie die volle Inkompatibilität riskieren. Wird also nie passieren. Was passieren kann, ist, daß irgendwann bspw. ein 4bytiger Zeichensatz eingeführt wird, dieser aber auch neue Funktionen, zB *WW() oder *WX() bekommt!

marabu 7. Sep 2005 16:41

Re: WideString in Stream speichern - Wie?
 
Hi Olli,

Zitat:

Zitat von Olli
Und genaugenommen können auch UTF-16-Zeichen schon bis 4 Bytes lang sein

wirklich? Oder wolltest du Unicode anstelle von UTF-16 schreiben - 4 byte characters nennt der Standard doch eigentlich UTF-32...

Grüße vom marabu

Olli 7. Sep 2005 16:54

Re: WideString in Stream speichern - Wie?
 
Zitat:

Zitat von marabu
wirklich? Oder wolltest du Unicode anstelle von UTF-16 schreiben - 4 byte characters nennt der Standard doch eigentlich UTF-32...

Nene, ist schon so gemeint.
http://www.unicode.org/faq/utf_bom.html#37

Was du unterschlägst sind die sog. "Surrogates" (Zeichen, die aus einer Kombination von einem "Leading 'Byte'" und dem Verweis in die "erweiterte" Zeichentabelle bestehen).

:mrgreen:

marabu 7. Sep 2005 17:16

Re: WideString in Stream speichern - Wie?
 
Zitat:

Zitat von Olli
Was du unterschlägst sind die sog. "Surrogates"

Tatsächlich, es gibt sie - theoretisch. Habe ein wenig geschmökert. Hast du schonmal welche gesehen? Abgesehen von Testdaten, meine ich?

Zitat:

The High Surrogate Area does not contain any character assignments, consequently no character code charts or namelists are provided for this area. Surrogates are reserved for use with UTF-16 and then must be used in pairs.
marabu

Olli 7. Sep 2005 17:25

Re: WideString in Stream speichern - Wie?
 
Zitat:

Zitat von marabu
Hast du schonmal welche gesehen? Abgesehen von Testdaten, meine ich?

Nö :mrgreen: ...

Beste Grüße an den marabu,

mael 7. Sep 2005 17:40

Re: WideString in Stream speichern - Wie?
 
Zitat:

Zitat von marabu
Zitat:

Zitat von Olli
Was du unterschlägst sind die sog. "Surrogates"

Tatsächlich, es gibt sie - theoretisch. Habe ein wenig geschmökert. Hast du schonmal welche gesehen? Abgesehen von Testdaten, meine ich?

Es sind selten verwendete Zeichen, darunter ungebräuchliche/veraltete asiatische Zeichen.
Alles über U+0FFFF muß als surrogate pair dargestellt werden, Details hier http://www.unicode.org/charts/


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