2009-01-31 32 views
5

Supponiamo che per qualche motivo perverso si voglia visualizzare il contenuto del byte grezzo di un UTF8String.Delphi 2009 RawByteString vagari

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

(1) Questo non lo fa, viene visualizzata la forma leggibile:

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

(2) Questo, tuttavia, non "lavoro" - nota la concatenazione:

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

Ho capito (1), anche se la coercizione forzata del compilatore a UnicodeString sembra impedire la visualizzazione di una variabile RawByteString come è. Tuttavia, perché il comportamento cambia in (2)?

(3) Ancora più strano - cerchiamo di invertire la concatenazione:

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

Ho letto in sui tipi stringa diavolerie a Delfi e ho pensato ho capito come funzionano, ma questo è un puzzle .

risposta

9

RawByteString esiste solo per ridurre al minimo il numero di sovraccarichi necessari per funzioni che funzionano con vari tipi di AnsiString s con diverse affinità della codepage.

In generale, non dichiarare variabili di tipo RawByteString. Non digitare valori per quel tipo. Non fare concatenazioni su variabili di quel tipo. Circa le uniche cose che si possono fare sono:

  • Dichiarare un parametro di questo tipo (l'intento originale)
  • indicizzazione su questo parametro
  • Ricerca in un tale parametro
  • operazioni intelligenti che controllano il la tabella codici effettiva della stringa, utilizzando la funzione StringCodePage.

Per esempio, si noterà che la funzione StringCodePage stesso usa RawByteString come il suo tipo di argomento. In questo modo, funzionerà con qualsiasi AnsiString, anziché eseguire una traduzione della codepage prima di passarla come argomento.

Per il tuo caso, cose come le concatenazioni sono in gran parte indefinite. Il comportamento è cambiato tra RTM e Update 2, ma quando le funzioni di concatenazione di stringhe RTL ricevono più stringhe con pagine di codice diverse, non esiste un modo semplice per capire quale pagina di codice deve essere utilizzata per la stringa finale. Questa è solo una delle ragioni per cui non dovresti concatenarli come fai qui.

+0

Thans, Barry, questo ha senso.La concatenazione era solo un esperimento "cosa succede se premevo questo pulsante", niente di pratico. Strano però per vedere Delphi introdurre un comportamento indefinito come questo - non ce ne sono mai stati molti prima. –

1

Non è possibile aggiungere una stringa a un TMemo "così com'è". Hai sempre bisogno di così una sorta di conversione a Unicode, perché questo è tutto TMemo conosce in Delphi 2009.

Se si vuole far finta che l'UTF8String utilizza il codice 1252, fare questo:

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

Per maggiori dettagli, vedi il mio articolo Using RawByteString Effectively

+0

UTF-8 è una codifica a 8 bit. Richiede codeunità $ 00- $ FF per essere elaborato così com'è. Tuttavia, la codepage 1252 associa code code $ 80- $ 9F a valori diversi quando viene convertita in UTF-16. Dovresti utilizzare la codepage 28591 (ISO-8859-1). –