Delphi Chaîne Unicode Longueur en Octets
Je suis en train de travailler sur le portage de certains Delphi 7 du code de XE4, donc, unicode est le sujet ici.
J'ai une méthode où une chaîne est écrite pour un TMemoryStream, selon cette embarcadero article, je devrais multiplier la longueur de la chaîne (de caractères) fois la taille du type Char pour obtenir la longueur, en octets, ce qui est nécessaire pour la longueur (en octets) paramètre WriteBuffer.
auparavant:
rawHtml : string; //AnsiString
...
memorystream1.WriteBuffer(Pointer(rawHtml)^, Length(rawHtml);
après:
rawHtml : string; //UnicodeString
...
memorystream1.WriteBuffer(Pointer(rawHtml)^, Length(rawHtml)* SizeOf(Char));
Ma compréhension de Delphi UnicodeString type, c'est que c'est de l'UTF-16 en interne. Mais ma compréhension générale de l'Unicode, c'est que pas tous les caractères unicode peuvent être représentés, même dans les 2 octets, que certains cas de coin caractères étrangers prendront 4 octets. Un autre de embarcadero articles semble confirmer mes soupçons, "En fait, il n'est même pas toujours vrai qu'un Char est égale à deux octets!"
Donc...qui me laisse penser que Length(rawHtml)* SizeOf(Char)
va vraiment être suffisamment robuste pour être toujours exactes, ou s'il existe une meilleure façon de déterminer la taille de la chaîne à être plus précis?
TStringStream
au lieu de TMemoryStream
?En fin de compte MemoryStream est passé à un composant TWebBrowser à afficher. Presque tous les exemple que j'ai vu de qui a utilisé MemoryStream. Serait StringStream être un meilleur choix pour ce but?
En fin de compte, ils sont tous deux basés sur une
TStream
ce qui signifie que la structure interne des deux fonctionnent de la même - c'est juste la façon dont vous interagissez avec elle c'est différent. De sorte que même une TFileStream
ou TResourceStream
sont applicables à l'utilisation dans votre cas, qui est, si vous avez été l'envoi de Fichiers ou Ressources à votre navigateur de toute façon.Ça me fait toujours mal que Delphi n'est pas d'utiliser l'UTF8 en interne.
TStringStream est TMemoryStream descendant, il est donc logique de le remplacer
OriginalL'auteur Jessica Brown | 2013-05-13
Vous devez vous connecter pour publier un commentaire.
Vous avez raison à propos de l'encodage UTF-16 de Delphi
UnicodeString
. Cela signifie que l'un de caractères 16 bits est assez large pour représenter tous les les points de code de la Plan Multilingue De Base exactement comme unChar
élément destring
tableau.Toutefois, vous avez eu un petit malentendu ici.
Length
fonction ne s'exécute pas tout d'une inspection en profondeur de caractères et renvoie le nombre de 16 bitsWideChar
éléments, sans prendre en compte les substituts au sein de votre chaîne. Cela signifie que si vous attribuer un caractère unique à partir de Plans Supplémentaires à laUnicodeString
,Length
sera de retour 2.Conclusion: taille en octets de la chaîne de données est toujours fixe et égale
Length(S) * SizeOf(Char)
, peu importe siS
contient toute la longueur variable des caractères.OriginalL'auteur OnTheFly
Delphi
UnicodeString
est encodé en UTF-16. UTF-16 est un codage à longueur variable, tout comme l'UTF-8. En d'autres termes, un seul point de code Unicode peut nécessiter plusieurs éléments de caractères à encoder. Comme un point d'intérêt, la seule longueur fixe l'encodage Unicode UTF-32. Le codage UTF-16 utilise 16 bits éléments de caractère, d'où le nom.En Unicode Delphi,
Char
est un alias pourWideChar
qui est un caractère UTF-16 de l'élément. Etstring
est un alias pourUnicodeString
, qui est un tableau deWideChar
éléments. LeLength()
fonction retourne le nombre d'éléments dans le tableau.Donc,
SizeOf(Char)
est toujours 2 pourUnicodeString
. Certains points de code Unicode codés à l'aide de plusieurs éléments de caractère, ouChar
s. MaisLength()
renvoie le nombre de caractères éléments et pas le nombre de points de code. Les éléments de caractères ont tous la même taille. Doncest correct.
OriginalL'auteur David Heffernan
D'autres ont expliqué comment UnicodeString est codé et la façon de calculer sa longueur en octets. Je veux juste mentionner que le RTL a déjà une telle fonction -
SysUtils.ByteLength()
:J'ai lu votre QC rapport. Votre "solution " proposée" n'est pas mieux, parce que le passage d'un
UnicodeString
à unRawByteString
encore effectue une conversion de données, cette fois à partir de l'UTF-16 Ansi, qui peut être figé.RawByteString
ne permet pas de conserverUnicodeString
de données, seulementAnsiString(N
) de données. La bonne solution est de surchargeByteLength()
surUnicodeString
etRawByteString
, comme d'autres RTL fonctions ne.Vous avez tout à fait raison. Je vais corriger mon QC rapport. C'est probablement une perte de temps, mais parce que le rapport n'a jamais été ouvert.
Après avoir corrigé, je peux pousser jusqu'à la prochaine niveau de.
Je pense que j'ai fixé maintenant. Merci pour votre aide.
OriginalL'auteur Remy Lebeau
Ce que vous faites est correct (avec la sizeof(Char)).
Ce que vous consultez est-ce pas un personnage se réfère à un seul point de code (en raison de paires de substitution par exemple). Mais le USC2 codé (PAS en UTF-16) des caractères dans la chaîne de prendre exactement la quantité d'octets avec
Length( Str ) * sizeof( Char )
.Noter que le codage Unicode utilisé dans Delphi est la même que pour toutes les API Windows s'attendre dans l' ....W variantes.
Dans UnicodeString UTF-16 est utilisé, pas le plus âgé de l'UCS-2. Donc, d'un point de code peut être composé d'un ou deux Caractères. Mais comme David l'a expliqué, une paire de substitution est à deux Caractères, et la Longueur qui compte le nombre de Char éléments, et non pas le nombre de points de code.
Windows chaînes UTF-16 depuis Windows 2000
OriginalL'auteur Ritsaert Hornstra