[英]Delphi Unicode String Length in Bytes
我正在努力將一些Delphi 7代碼移植到XE4,因此,unicode就是這里的主題。
我有一個方法,其中一個字符串被寫入TMemoryStream,所以根據這篇embarcadero文章 ,我應該將字符串的長度(以字符為單位)乘以Char類型的大小,以獲得所需的字節長度。 WriteBuffer的長度(以字節為單位)參數。
所以之前:
rawHtml : string; //AnsiString
...
memorystream1.WriteBuffer(Pointer(rawHtml)^, Length(rawHtml);
后:
rawHtml : string; //UnicodeString
...
memorystream1.WriteBuffer(Pointer(rawHtml)^, Length(rawHtml)* SizeOf(Char));
我對Delphi的UnicodeString類型的理解是它內部是UTF-16。 但我對Unicode的一般理解是,即使是2個字節也不能表示所有unicode字符,有些角落外殼字符將占用4個字節。 embarcadero的另一篇文章似乎證實了我的懷疑,“事實上,一個Char等於兩個字節甚至不總是這樣!”
所以...這讓我想知道Length(rawHtml)* SizeOf(Char)
是否真的足夠穩健以保持一致,或者是否有更好的方法來確定更准確的字符串大小?
Delphi的UnicodeString
使用UTF-16編碼。 UTF-16是一種可變長度編碼,就像UTF-8一樣。 換句話說,單個Unicode代碼點可能需要多個字符元素來對其進行編碼。 作為一個興趣點,唯一的固定長度Unicode編碼是UTF-32。 UTF-16編碼使用16位字符元素,因此名稱。
在Unicode Delphi中, Char
是WideChar
的別名,它是UTF-16字符元素。 string
是UnicodeString
的別名, UnicodeString
是WideChar
元素的數組。 Length()
函數返回數組中的元素數。
因此,對於UnicodeString
, SizeOf(Char)
始終為2。 某些Unicode代碼點使用多個字符元素或Char
來編碼。 但Length()
返回字符元素的數量而不是代碼點的數量。 字符元素都具有相同的大小。 所以
memorystream1.WriteBuffer(Pointer(rawHtml)^, Length(rawHtml)* SizeOf(Char));
是正確的。
我對Delphi的UnicodeString類型的理解是它內部是UTF-16。
你對Delphi的UnicodeString
UTF-16編碼是正確的。 這意味着一個16位字符的寬度足以將基本多語言平面中的所有代碼點表示為string
數組的一個Char
元素。
但我對Unicode的一般理解是,即使是2個字節也不能表示所有unicode字符,有些角落外殼字符將占用4個字節。
但是,你在這里有一點誤解。 Length
函數不會對字符執行任何深度檢查,只返回16位WideChar
元素的數量,而不考慮字符串中的任何代理。 這意味着如果將任何補充平面中的單個字符分配給UnicodeString
,則Length
將返回2。
program Egyptian;
{$APPTYPE CONSOLE}
var
S: UnicodeString;
begin
S := #$1304E; // single char
Writeln(Length(S));
Readln;
end.
結論 :無論S
包含任何可變長度字符,字符串數據的字節大小始終是固定的並且等於Length(S) * SizeOf(Char)
。
其他人已經解釋了如何編碼UnicodeString以及如何計算其字節長度。 我只想提一下RTL已經有了這樣的功能SysUtils.ByteLength()
:
memorystream1.WriteBuffer(PChar(rawHtml)^, ByteLength(rawHtml));
你正在做的是正確的(使用sizeof(Char))。
你所指的是,沒有一個字符指代一個代碼點(例如,由於代理對)。 但是字符串中的USC2編碼(非UTF-16)字符恰好占用了Length( Str ) * sizeof( Char )
的字節數。
請注意,Delphi中使用的Unicode編碼與.... W變體中的所有Windows API調用相同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.