在Delphi 2009下将字符串保存到磁盘

时间:2009-03-07 23:53:10

标签: delphi delphi-2009 save

我有一个类似下面的结构需要保存并从磁盘加载。

 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;

到目前为止,我已经使用过这样的东西来保存结构:

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

上面的代码在Delphi 7下工作。在D2009下,当我在短字符串和Unicode字符串之间进行分配时,我收到了很多警告信息。 到目前为止,我设法编写Delphi代码而没有任何编译器警告或提示,我想保持这样。 所以我需要一个优雅的方法是将磁盘保存(Unicode将很好但不是关键)到磁盘而不会收到警告。

3 个答案:

答案 0 :(得分:8)

Delphi 2009中的字符串字段与以前的所有版本相同。 ShortString不是Unicode类型。

所以你应该可以继续按原样使用该记录。

你说它在Delphi 7中有效。在Delphi 2009中它吗?描述你遇到的问题。

你的意思是说你想要一个等长于ShortString的固定长度的Unicode吗?没有一个,所以你不能有这样的记录,让它保持类似字符串的Unicode值,并将其直接保存到磁盘。

我不认为这是一个主要问题,因为你的磁盘格式无论如何都与你当前的格式不兼容:你的角色太大了。

您可以使用字符数组:

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;

这不会像真正的字符串类型那样方便,但它可以用于大多数目的。

您还可以使用普通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;

您无法再将其直接保存到磁盘,但您不再限制为255个字符。您必须分别存储每个字符串字段。确保也存储字符串的长度,或者你不知道一个字符串的结束位置,以及下一个字符串的开始时间。

答案 1 :(得分:6)

或者,您可以声明可存储的短unicode字符串记录,并实现隐式'to string'和'from string'转换。

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.

[上述代码已发布到公共领域,不承担任何许可证义务。]

答案 2 :(得分:2)

您可以保留现有结构(字符串[255]),现有文件格式,甚至可以使用以下内容正确读取先前保存的非unicode数据:

在写数据之前:

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

阅读数据后:

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