1

我有一个像下面这样的结构,需要从磁盘保存和加载。

 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 很好但不是关键)保存到磁盘而不收到警告。

4

3 回答 3

8

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

因此,您应该能够按原样继续使用该记录。

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

你的意思是说你想要一个等价于的固定长度的Unicode ShortString?没有,所以你不能有这样的记录,让它保存类似字符串的 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 个字符。您必须分别存储每个字符串字段。确保也存储字符串的长度,否则在稍后加载文件时,您将不知道一个字符串在哪里结束,而下一个字符串从哪里开始。

于 2009-03-08T00:13:48.033 回答
6

或者,您可以声明可存储的短 unicode 字符串记录并实现隐式“到字符串”和“从字符串”转换。

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.

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

于 2009-03-08T08:49:46.140 回答
2

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

在写入数据之前:

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

读取数据后:

...
Name:= UTF8ToString(record.Name);
于 2009-11-27T06:56:29.470 回答