2010-11-04 2 views
12

Sto scrivendo una classe che salverà le stringhe ampie in un file binario. Sto usando Delphi 2005 per questo, ma l'applicazione verrà successivamente portato su Delphi 2010. Mi sento molto insicuro qui, qualcuno può confermare che:Delphi WideString e Delphi 2009+

  1. A Delphi 2005 WideString è esattamente lo stesso tipo come Delphi 2010 String

  2. a Delphi 2005 WideString char così come un Delphi 2010 String char è garantita sempre essere di 2 byte.

Con tutta l'Unicode formati là fuori io non voglio essere colpito con uno dei caratteri nella mia stringa di essere improvvisamente 3 byte di larghezza o qualcosa di simile.

Edit: mappe "Ho infatti detto UnicodeString, non WideString WideString esiste ancora, ed è invariato WideString viene assegnato dal gestore di memoria di Windows, e dovrebbe essere usato per interagire con gli oggetti COM WideString: trovato questo... direttamente al tipo BSTR in COM. " al http://www.micro-isv.asia/2008/08/get-ready-for-delphi-2009-and-unicode/

Ora sono ancora più confuso. Quindi un Delphi 2010 WideString non è la stessa di Delphi 2005 WideString? Dovrei usare invece UnicodeString?

Modifica 2: Non c'è il tipo UnicodeString in Delphi 2005. FML.

+2

Perché si concludere che Delphi 2010 WideString non è la stessa di un Delphi 2005 WideString dopo aver letto una dichiarazione che dice "WideString esiste ancora ed è invariato"? –

risposta

1
  1. A Delphi 2005 WideString è esattamente lo stesso tipo di Delphi 2010 String

Questo non è vero - ex Delphi 2010 stringa ha nascosto campo tabella codici interna - ma probabilmente non importa per voi.

  1. Un char di Delphi 2005 WideString e un char di Delphi 2010 garantisce sempre una dimensione di 2 byte.

Questo è vero. In Delphi 2010 SizeOf (Char) = 2 (Char = WideChar).


Non ci può essere tabella codici diversi per le stringhe Unicode - campo tabella di codici è stato introdotto per creare un formato comune binario per entrambe le stringhe Ansi (quel campo bisogno tabella codici) e stringa Unicode (che non ne hanno bisogno).

Se si salvano i dati WideString in streaming in Delphi 2005 e si caricano gli stessi dati nella stringa in Delphi 2010, tutto dovrebbe funzionare correttamente.

WideString = BSTR e che non è cambiato tra Delphi 2005 e il 2010

UnicodeString = WideString in Delphi 2005 (se il tipo UnicodeString esiste in Delphi 2005 - non so) UnicodeString = stringa in Delphi 2009 e sopra.


@Marco - Ansi e Unicode stringhe in Delphi 2009+ hanno formato binario comune (intestazione 12-byte).

UnicodeString codepage CP_UTF16 = 1200;

+0

Quindi, se salgo una WideString in Delphi 2005 usando Stream.Scrivi (AWideString [1], 2 * Length (AWideString)) e viene caricato con una versione di Delphi 2010 dell'app che utilizza una codepage diversa, cosa succederà? Devo salvare anche la codepage insieme alle stringhe? – David

+0

Non puoi contare su SizeOf (Char) = 2 per la versione futura, quindi non usare 2, ma usa SizeOf (Char). Siamo impegnati nel porting del vecchio codice al 2010 e ci sono molte ipotesi (SizeOf (Char) = 1) che ci stanno facendo impazzire. –

+0

Non ero a conoscenza del fatto che Tunicodestring avesse un campo di codepage? Pensavo che solo l'ansare avesse? –

12

Per la prima domanda: WideString non è esattamente lo stesso tipo della stringa di D2010. WideString è lo stesso tipo COM BSTR che è sempre stato. È gestito da Windows, senza contare i riferimenti, quindi esegue una copia dell'intero BSTR ogni volta che lo passi da qualche parte.

UnicodeString, che è l'impostazione predefinita stringa tipo in D2009 e, è fondamentalmente una versione UTF-16 del AnsiString che tutti noi conosciamo e amiamo. Ha un conteggio dei riferimenti ed è gestito dal compilatore Delphi.

Per il secondo, il tipo predefinito char è ora WideChar, che sono gli stessi caratteri che sono sempre stati utilizzati in WideString. È una codifica UTF-16, 2 byte per carattere. Se si salvano i dati WideString in un file, è possibile caricarli in un UnicodeString senza problemi. La differenza tra i due tipi ha a che fare con la gestione della memoria, non con il formato dei dati.

+0

Ma non c'è un tipo UnicodeString in Delphi 2005! Sono un po 'sfortunato? Non voglio usare WideString se non è lo stesso di una stringa di Delphi 2010. – David

+0

@David: controlla le ultime due frasi. I dati della stringa sono esattamente gli stessi. Ciò che è diverso è che 'UnicodeString' utilizza un modello di gestione della memoria più efficiente. –

+0

Unicodestring è più o meno il più grande di Kylix. –

4

Come già menzionato, il tipo di dati stringa (in realtà UnicodeString) in Delphi 2009 e versioni successive non è equivalente al tipo di dati WideString nelle versioni precedenti, ma il formato del contenuto dei dati è lo stesso. Entrambi salvano la stringa in UTF-16. Quindi, se salvi un testo usando WideString nelle versioni precedenti di Delphi, dovresti essere in grado di leggerlo correttamente usando il tipo di dati stringa nelle versioni recenti di Delphi (2009 e successive).

È necessario tenere presente che le prestazioni di UnicodeString sono superiori a quelle di WideString. Quindi, se avete intenzione di utilizzare lo stesso codice sorgente sia in Delphi 2005 e Delphi 2010, vi consiglio di utilizzare un tipo di stringa alias con compilazione condizionale nel codice, in modo che si può avere il meglio dei due mondi:

type 
    {$IFDEF Unicode} 
    MyStringType = UnicodeString; 
    {$ELSE} 
    MyStringType = WideString; 
    {$ENDIF} 

Ora puoi utilizzare MyStringType come tipo di stringa nel codice sorgente. Se il compilatore è Unicode (Delphi 2009 e versioni successive), il tipo di stringa sarà un alias di tipo UnicodeString introdotto in Delphi 2009 per contenere stringhe Unicode. Se il compilatore non è unicode (ad esempio Delphi 2005), il tipo di stringa sarà un alias per il vecchio tipo di dati WideString. E poiché entrambi sono UTF-16, i dati salvati da una qualsiasi delle versioni dovrebbero essere letti correttamente dall'altra.

+10

Invece di definire un nuovo nome di stringa, è possibile farlo: '{$ IFNDEF Unicode} tipo UnicodeString = WideString; {$ ENDIF}'. In questo modo, il tuo codice non è disseminato del nome di un tipo non standard. –

+0

Sì, sarebbe una soluzione migliore. Grazie. – vcldeveloper

0

La regola è semplice:

  • Se si desidera lavorare con le stringhe Unicode all'interno del modulo solo - usare UnicodeString tipo (*).
  • Se si desidera comunicare con COM o con altri scopi cross-module, utilizzare il tipo WideString.

Vedete, WideString è un tipo speciale, poiché non è di tipo Delphi nativo. È un alias/wrapper per BSTR - un tipo di stringa di sistema, intenzionale per l'utilizzo con comunicazioni COM o tra moduli. Essere un unicode - è solo un effetto collaterale.

D'altra parte, AnsiString e UnicodeString - sono tipi Delphi nativi, che non hanno l'analogico in altre lingue.String è solo un alias per AnsiString o UnicodeString.

Quindi, se è necessario passare una stringa ad un altro codice, utilizzare WideString, altrimenti: utilizzare AnsiString o UnicodeString. Semplice.

P.S.

(*) Per i vecchi Delphi - è sufficiente posizionare

{$IFNDEF Unicode} 

type 
    UnicodeString = WideString; 

{$ENDIF} 

da qualche parte nel codice. Questa correzione ti consentirà di scrivere lo stesso codice per qualsiasi versione di Delphi.

0

Mentre un char D2010 è sempre e esattamente 2 byte, gli stessi problemi di piegatura e combinazione dei caratteri sono presenti nei caratteri UTF-16 come nei caratteri UTF-8. Non lo si vede con stringhe strette perché sono basate sulla codepage, ma con le stringhe Unicode è possibile (e in alcune situazioni comuni) avere caratteri affettivi ma non visibili. Gli esempi includono il byte order mark (BOM) all'inizio di un file Unicode o stream, caratteri da sinistra a destra/destra a sinistra, e una vasta gamma di combinazioni di accenti. Questo riguarda principalmente le domande su "quanti pixel di larghezza sarà questa stringa sullo schermo" e "quante lettere sono in questa stringa" (a differenza di "quanti caratteri ci sono in questa stringa"), ma significa anche che puoi " t casualmente tritare caratteri da una stringa e assumere che siano stampabili. Operazioni come "rimuovere l'ultima lettera da questa parola" diventano non banali e dipendono dalla lingua in uso.

La domanda su "uno dei caratteri nella mia stringa è improvvisamente lunga 3 byte" riflette un po 'di confusione su come funziona UTF. È possibile (e valido) prendere tre byte in una stringa UTF-8 per rappresentare un carattere stampabile, ma ogni byte sarà un carattere UTF-8 valido. Di 'una lettera più due accenti combinati. Non si otterrà un carattere in UTF-16 o UTF-32 con una lunghezza di 3 byte, ma potrebbe essere lungo 6 byte (o 12 byte), se è rappresentato utilizzando tre punti di codice in UTF-16 o UTF-32. Il che ci porta alla normalizzazione (o meno).

Ma a patto di avere a che fare con le stringhe come cose intere, è tutto molto semplice: basta prendere la stringa, scriverla in un file, quindi rileggerla. Non devi preoccuparti della multa stampa di visualizzazione e manipolazione delle stringhe, gestita dal sistema operativo e dalle librerie. Strings.LoadFromFile (nome) e Listbox.Items.Add (stringa) funzionano esattamente nello stesso modo in D2010 come in D2007, la roba Unicode è completamente trasparente per te come programmatore.

0

Sto scrivendo una classe che salverà le stringhe ampie in un file binario.

Quando si scrive la classe nella D2005 si prevede di utilizzare WideString Quando si migra a D2010 WideString saranno ancora validi e funzionare correttamente. La larghezza massima in D2005 è la stessa di WideString in D2010.

Il fatto che String = WideString in D2010 non deve essere considerato poiché il compilatore gestisce facilmente tali problemi.

Vostra routine di ingresso per salvare con (astring: String) hanno bisogno di una sola linea di entrare nel proc

procedure SaveAStringToBIN_File(AString:String); 
var wkstr : Widestring; 
begin 
{$IFDEF Unicode} wkstr := AString;  
{$ELSE}   wkstr := UTF8Decode(AString); {$ENDIF} 
... 
    the rest is the same saving a widestring to a file stream 
    write the length (word) of string then data 

end;