Pergunta

Eu tenho uma estrutura como abaixo que precisa ser salvos e carregados a partir do 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;

Até agora eu usei algo parecido com isso para salvar a estrutura:

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

O código acima trabalhou sob Delphi 7. Em D2009 eu tenho um monte de mensagens de aviso quando eu faço atribuições entre seqüências curtas e Unicode. Até agora eu consegui escrever código Delphi sem ter qualquer avisos do compilador ou sugestões e eu quero ficar assim. Então eu preciso de um elegante era salvar cordas (Unicode será grande, mas não crítico) para o disco sem receber avisos.

Foi útil?

Solução

Alternatively, you can declare storable short unicode string record and implement implicit 'to string' and 'from string' conversions.

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.

[The code above is released to public domain and carries no license obligations.]

Outras dicas

Those string fields are the same in Delphi 2009 as they were in all previous versions. ShortString is not a Unicode type.

So you should be able to continue using that record as-is.

You say it worked in Delphi 7. Does it not work in Delphi 2009? Describe the problem you're having.

Do you mean to say that you want a fixed-length Unicode equivalent to ShortString? There isn't one, so you can't have a record like that, have it hold string-like Unicode values, and save it directly to disk.

I don't think that's a major problem, though, since your disk format wouldn't be compatible with your current format anyway: your characters would be too big.

You can use an array of characters:

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;

That's not going to be quite as convenient as real string types, but it will work for most purposes.

You can also use a normal UnicodeString type:

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;

You can't save that directly to disk anymore, but you're also no longer limited to 255 characters. You'll have to store each string field separately. Make sure to store the string's length, too, or you won't know where one string ends and the next begins when it comes time to load your file later.

You can keep existing structure (string[255]), existing file format and even correctly read non-unicode data previously saved by using the following:

before writing data:

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

after reading data:

...
Name:= UTF8ToString(record.Name);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top