0

TStringListを使用するバックアップシステムがありますが、古いDelphi(Ansi文字列)でコーディングしています。

基本的に私は保存するときにこれを持っています:

...
MyStringList.SaveToStream(Str);
StrSz := Str.Size;
MyBackupStream.Write(StrSz, SizeOf(Integer));
MyBackupStream.Write(Str.Memory^, StrSz);
...

そして私がリロードするとき:

...
MyBackupStream.Read(StrSz, SizeOf(Integer));
Str.SetSize(StrSz);
MyBackupStream.Read(Str.Memory^, StrSz);
MyStringList.SetText := PChar( Str.Memory);
...

このシーケンシャル(サイズ+データサイズバイト、次にサイズ+データサイズバイトなど)システムをさまざまなコンポーネントのバックアップに使用します。実際、一部のものは、stringlistバックアップの前に常に「読み取り元」または「書き込み先」になります(つまり、StringListバックアップの前後にいくつかのデータがあります)。

ここで大きな問題を紹介していますか(最新のDelphiバージョンに切り替える場合)?チャンクは、将来のdelphiバージョンでもキャスト可能ですか(切り替えた場合)。バックアップヘッダーに文字列バージョンを書き込む必要がありますか?

残念ながら、これをテストすることはできません。少なくともヘッダーに文字列エンコーディングタイプを記述すれば、Delphiのバージョンが何であれ、後で正しい方法でキャストできるようになると思いますね。

4

2 に答える 2

2

MyStringList.LoadFromStream(Str)の代わりに使用しMyStringList.Text := PChar( Str.Memory)ます。

まず、TStreamデータは null で終了しませんがPChar、この方法を使用するには null ターミネータが必要です (SetString()文字列変数を使用してそれを回避できます)。

2 つ目は、D2009 以降、Stringがから に変わり、がに変わりましUnicodeStringた。データは Unicode ではなく Ansi です (D2009+ でも、ストリーム データのエンコードにデフォルトで Ansi を使用するため)。そのため、データを にキャストすると、.AnsiStringPCharPWideCharPAnsiCharTStreamSaveToStream()TEncoding.DefaultPWideCharTStringList

すべてのバージョンで を使用する必要がありますがLoadFromStream()、プロパティの設定に固執する場合は、次のTextようにする必要があります。これはすべてのバージョンで機能します。

var
  ...
  S: AnsiString;
begin
  ...
  MyBackupStream.ReadBuffer(StrSz, SizeOf(Integer));
  Str.SetSize(StrSz);
  if StrSz > 0 then MyBackupStream.ReadBuffer(Str.Memory^, StrSz);
  SetString(S, PAnsiChar(Str.Memory), StrSz);
  MyStringList.Text := String(S);
  ...
end;

またはこれ:

var
  ...
  S: AnsiString;
begin
  ...
  MyBackupStream.ReadBuffer(StrSz, SizeOf(Integer));
  if StrSz > 0 then begin
    SetLength(S, StrSz);
    MyBackupStream.ReadBuffer(S[1], StrSz);
  end;
  MyStringList.Text := String(S);
  ...
end;

またはこれ:

var
  ...
  Str: TStringStream;
begin
  ...
  Str := TStringStream.Create;
  try
    MyBackupStream.ReadBuffer(StrSz, SizeOf(Integer));
    if StrSz > 0 then Str.CopyFrom(MyBackupStream, StrSz);
    MyStringList.Text := Str.DataString;
  finally
    Str.Free;
  end;
  ...
end;

最後に、将来の互換性をさらに高めるために、ストリーム データを Ansi ではなく UTF-8 を使用するように変更することを検討する必要があります。と の両方SaveToStream()にD2009+LoadFromStream()のオプションTEncodingパラメータがあり、UTF-8 は可逆 Unicode エンコーディングですが、Ansi は Ansi/Unicode 変換中にデータを失う可能性があります。既存のデータが ASCII ( AnsiChar#127 を超える文字がない) の場合、UTF-8 は ASCII と 100% 後方互換性があります。ただし、データが代わりに Ansi である場合 ( AnsiChar#127 を超える文字が含まれる)、ストリーム形式を何らかの方法で変更 (ヘッダー/バージョンを追加するなど) して、古い形式と新しい形式を区別できるようにすることをお勧めします。 Ansi を使用して古い形式を保存し、Unicode/UTF-8 を使用して新しい形式を保存/読み込みます。

于 2011-11-06T00:23:13.833 に答える
1

あなたは正しい軌道に乗っていると思います。数年前、私もあなたと同じような仕事をしたことを覚えています。データの各チャンクには、ヘッダーとコンテンツの 2 つのセクションがありました。ヘッダーには、開始アドレスやチャンクの長さなどの情報が含まれていました。コンテンツ部分には実際のデータが含まれていました。このアプローチで問題が発生することはありませんでした。あなたの場合、ヘッダーにはブロックのサイズのみが含まれていました。string のバージョン番号については、Delphi のリリース ロードに基づいて、新しいリリースが古いリリースと下位互換性がないことが非常に一般的であるため、そうすることをお勧めします。後でバージョン番号を使用する必要がない場合でも、害はありません。

于 2011-11-05T23:27:09.943 に答える