Domanda

Ho una struttura come quella sotto che deve essere salvata e caricata dal disco.

 RSecStructure= packed record
   Name               : string[255];       {NEED UNICODE SUPPORT HERE}
   ScreenName         : string[255];
   OrigFileName       : string[255];                    
   Prim               : string[255];                                           
   ParentVersion      : integer;
   sTag1              : string[255];      
   sTag2              : string[255];
   sTag3              : string[255];
   sTag4              : string[255];
   DateAdd            : TDateTime;
   DateModify         : TDateTime;
  end;

Fino ad ora ho usato qualcosa del genere per salvare la struttura:

function
var F: FILE;
    Hdr: RSecStructure;
begin
...
 BlockWrite (F, Hdr, SizeOf(Hdr));   
...
end

Il codice sopra ha funzionato sotto Delphi 7. Sotto D2009 ho ricevuto molti messaggi di avviso quando faccio assegnazioni tra stringhe brevi e Unicode. Fino ad ora sono riuscito a scrivere il codice Delphi senza NESSUNA avvertenza o suggerimento per il compilatore e voglio rimanere così. Quindi ho bisogno di un modo elegante per salvare le stringhe (Unicode sarà fantastico ma non critico) su disco senza ricevere avvisi.

È stato utile?

Soluzione

In alternativa, puoi dichiarare record di stringhe Unicode memorizzabili e implementare conversioni implicite "in stringa" e "da stringa".

program TestShortUnicodeString;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TShortUnicodeString = record
  private
    Data: array [0..255] of char; //WARNING - NOT initialized to an empty string
  public
    class operator Implicit(const sus: TShortUnicodeString): string; inline;
    class operator Implicit(const ws: string): TShortUnicodeString; inline;
  end;

class operator TShortUnicodeString.Implicit(const sus: TShortUnicodeString): string;
begin
  Result := StrPas(sus.Data);
end;

class operator TShortUnicodeString.Implicit(const ws: string): TShortUnicodeString;
begin
  // too long strings are silently truncated
  StrPLCopy(Result.Data, ws, Length(Result.Data)-1);
end;

type
  TTestRec = record
    ws1: TShortUnicodeString;
    ws2: TShortUnicodeString;
  end;

var
  f    : file;
  test1: TTestRec;
  test2: TTestRec;

begin
  test1.ws1 := '6*9 =';
  test1.ws2 := ' 42';
  AssignFile(f, 'test.dat');
  Rewrite(f, 1);
  BlockWrite(f, test1, SizeOf(test1));
  CloseFile(f);
  AssignFile(f, 'test.dat');
  Reset(f, 1);
  Assert(FileSize(f) = SizeOf(test2));
  BlockRead(f, test2, SizeOf(test2));
  CloseFile(f);
  Writeln(string(test2.ws1), string(test2.ws2));
  Readln;
end.

[Il codice sopra è rilasciato al pubblico dominio e non comporta alcun obbligo di licenza.]

Altri suggerimenti

Questi campi stringa sono gli stessi in Delphi 2009 come in tutte le versioni precedenti. ShortString non è un tipo Unicode.

Quindi dovresti essere in grado di continuare a usare quel record così com'è.

Dici che ha funzionato in Delphi 7. non funziona in Delphi 2009? Descrivi il problema che stai riscontrando.

Intendi dire che vuoi un Unicode a lunghezza fissa equivalente a ShortString ? Non ce n'è uno, quindi non puoi avere un record del genere, avere valori Unicode simili a stringhe e salvarlo direttamente sul disco.

Non penso che sia un grosso problema, dal momento che il formato del tuo disco non sarebbe comunque compatibile con il tuo formato attuale: i tuoi personaggi sarebbero troppo grandi.

Puoi usare un array di caratteri:

type
  TSecStructure = packed record
    Name               : array[0..255] of UnicodeChar;
    ScreenName         : array[0..255] of UnicodeChar;
    OrigFileName       : array[0..255] of UnicodeChar;
    Prim               : array[0..255] of UnicodeChar;
    ParentVersion      : integer;
    sTag1              : array[0..255] of UnicodeChar;
    sTag2              : array[0..255] of UnicodeChar;
    sTag3              : array[0..255] of UnicodeChar;
    sTag4              : array[0..255] of UnicodeChar;
    DateAdd            : TDateTime;
    DateModify         : TDateTime;
  end;

Non sarà abbastanza conveniente come i tipi di stringa reali, ma funzionerà per la maggior parte degli scopi.

Puoi anche usare un normale UnicodeString :

type
  TSecStructure = record
    Name               : UnicodeString;
    ScreenName         : UnicodeString;
    OrigFileName       : UnicodeString;
    Prim               : UnicodeString;
    ParentVersion      : integer;
    sTag1              : UnicodeString;
    sTag2              : UnicodeString;
    sTag3              : UnicodeString;
    sTag4              : UnicodeString;
    DateAdd            : TDateTime;
    DateModify         : TDateTime;
  end;

Non puoi più salvarlo direttamente su disco, ma non sei più limitato a 255 caratteri. Dovrai memorizzare ciascun campo stringa separatamente. Assicurati di memorizzare anche la lunghezza della stringa, altrimenti non saprai dove finisce una stringa e la successiva inizia quando arriva il momento di caricare il tuo file in seguito.

Puoi mantenere la struttura esistente (stringa [255]), il formato di file esistente e persino leggere correttamente i dati non Unicode precedentemente salvati usando quanto segue:

prima di scrivere i dati:

...
record.Name:= UTF8EncodeToShortString(Name);

dopo aver letto i dati:

...
Name:= UTF8ToString(record.Name);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top