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 でも以前のすべてのバージョンと同じです。ShortStringUnicode タイプではありません。

したがって、そのレコードをそのまま使用し続けることができるはずです。

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 文字の制限もなくなりました。各文字列フィールドを個別に保存する必要があります。文字列の長さも忘れずに保存してください。そうしないと、後でファイルをロードするときに、1 つの文字列がどこで終わり、次の文字列が始まるかわかりません。

于 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

以下を使用して、既存の構造 (string[255])、既存のファイル形式を保持し、以前に保存された非 Unicode データを正しく読み取ることもできます。

データを書き込む前に:

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

データを読み取った後:

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