Salvataggio di stringhe su disco in Delphi 2009
-
05-07-2019 - |
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.
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);