2009-01-31 100 views
5

假設出於某種不正當的原因想要顯示UTF8String的原始字節內容。Delphi 2009 RawByteString變幻莫測

var 
    utf8Str : UTF8String; 
begin  
    utf8Str := '€ąćęłńóśźż'; 
end; 

(1)這不這樣做,它顯示可讀形式:

memo1.Lines.Add(RawByteString(utf8Str)); 
// output: '€ąćęłńóśźż' 

(2)然而,這並不 「工作」 - 注意級聯:

memo1.Lines.Add('x' + RawByteString(utf8Str)); 
// output: 'x€ąćęłńóśźż' 

我知道(1),雖然編譯器強制轉向UnicodeString似乎可以防止顯示RawByteString var原樣。但是,爲什麼行爲在(2)中改變?

(3)更奇怪的是 - 讓我們反向串聯:

memo1.Lines.Add(RawByteString(utf8Str) + 'x'); 
// output: '€ąćęłńóśźżx' 

我已經在德爾福新奇的字符串類型讀了,我想我明白他們是如何工作的,但是這是一個謎。

回答

9

RawByteString只存在於最大限度地減少功能所需的重載次數,這些重載功能可用於具有不同代碼頁親和力的各種風格的AnsiString

通常,不要聲明類型爲RawByteString的變量。不要爲此類型指定值。不要對該類型的變量進行連接。關於你唯一可以做的事情是:

  • 聲明這種類型的參數(原意)
  • 索引這樣的參數
  • 在這樣的參數搜索
  • ,辦理入住手續的智能操作字符串的實際代碼頁,使用StringCodePage函數。

例如,您會注意到StringCodePage函數本身使用RawByteString作爲其參數類型。這樣,它將與任何AnsiString一起工作,而不是在將它作爲參數傳遞之前進行代碼頁翻譯。

對於你的情況,像串聯這樣的事情在很大程度上是不確定的。行爲在RTM和Update 2之間發生了變化,但是當RTL字符串連接函數接收到具有不同代碼頁的多個字符串時,找不到最終字符串應使用哪個代碼頁的簡單方法。這就是爲什麼你不應該像在這裏一樣連接它們的原因之一。

+0

Thans,Barry,這很有道理。級聯只是一個「如果我按下這個按鈕」實驗,沒有任何實際價值。 奇怪的是,雖然看到德爾福引入了這樣一個未定義的行爲 - 從來沒有很多這樣的。 – 2009-01-31 19:22:23

1

您無法將字符串「按原樣」添加到TMemo。你總是需要這樣的某種轉換爲Unicode的,因爲這是所有TMemo知道在Delphi 2009年

如果你想假裝你的UTF8字符串使用代碼頁1252,這樣做:

var 
    utf8Str : UTF8String; 
    Raw: RawByteString; 
begin 
    utf8Str := '€ąćęłńóśźż'; 
    Raw := utf8Str; 
    SetCodePage(Raw, 1252, False); 
    Memo.Lines.Add(Raw); 
end; 

對於更多細節,請參閱我的文章Using RawByteString Effectively

+0

UTF-8是一個8位編碼。它要求代碼單元$ 00- $ FF按原樣處理。但是,當轉換爲UTF-16時,代碼頁1252將代碼單元$ 80- $ 9F映射到不同的值。您應該使用代碼頁28591(ISO-8859-1)。 – 2016-04-07 02:49:22