Question

J'ai une structure comme ci-dessous qui doit être enregistrée et chargée à partir du disque.

 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;

Jusqu'à présent, j'ai utilisé quelque chose comme ceci pour enregistrer la structure:

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

Le code ci-dessus a fonctionné sous Delphi 7. Sous D2009, de nombreux messages d'avertissement se sont glissés lorsque j'effectue des assignations entre des chaînes courtes et des chaînes Unicode. Jusqu'à présent, j'ai réussi à écrire du code Delphi sans avoir AUCUN avertisseur ni astuce du compilateur et je veux rester comme ça. Donc, j'ai besoin d'un élégant était de sauvegarder les chaînes (Unicode sera génial, mais pas critique) sur le disque sans avoir des avertissements.

Était-ce utile?

La solution

Vous pouvez également déclarer un enregistrement de chaîne unicode abrégé stockable et implémenter des conversions implicites "vers une chaîne" et "à partir d'une chaîne".

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.

[Le code ci-dessus est publié dans le domaine public et ne comporte aucune obligation de licence.]

Autres conseils

Ces champs de chaîne sont les mêmes dans Delphi 2009 et dans toutes les versions précédentes. ShortString n'est pas un type Unicode.

Vous devriez donc pouvoir continuer à utiliser cet enregistrement tel quel.

Vous dites que cela a fonctionné dans Delphi 7. Cela ne fonctionne-t-il pas dans Delphi 2009? Décrivez le problème que vous rencontrez.

Voulez-vous dire que vous voulez un équivalent Unicode de longueur fixe pour ShortString ? Il n'y en a pas, vous ne pouvez donc pas créer un tel enregistrement, le conserver avec des valeurs Unicode de type chaîne et l'enregistrer directement sur le disque.

Je ne pense pas que ce soit un problème majeur car votre format de disque ne serait de toute façon pas compatible avec votre format actuel: vos caractères seraient trop gros.

Vous pouvez utiliser un tableau de caractères:

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;

Cela ne sera pas aussi pratique que les types de chaînes réels, mais cela fonctionnera dans la plupart des cas.

Vous pouvez également utiliser un type UnicodeString normal:

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;

Vous ne pouvez plus enregistrer cela directement sur le disque, mais vous n'êtes plus limité à 255 caractères. Vous devrez stocker chaque champ de chaîne séparément. Assurez-vous également de stocker la longueur de la chaîne, sinon vous ne saurez pas où une chaîne se termine et où commence la suivante, au moment de charger votre fichier ultérieurement.

Vous pouvez conserver la structure existante (chaîne [255]), le format de fichier existant et même lire correctement les données non-Unicode précédemment enregistrées à l'aide des éléments suivants:

avant d'écrire des données:

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

après avoir lu les données:

...
Name:= UTF8ToString(record.Name);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top