1

TStringStreamでは、bytesそのBytesプロパティの使用は、を使用してbytes抽出されたものとは異なりTStream.Readます。以下に示すように:

  1. bytes抽出されたを使用して、TStream.Read正しいデータを表します。
  2. そのプロパティbytesを使用すると、より多くのデータが含まれます。Bytes(正しいの最後のバイトはbytes間違ったものとは異なりますbytes

考えられる理由についてコメントしていただけますか?ご助力ありがとうございます!

PS:Delphi XE、Windows7(Delphi 7に戻ったTStringStreamにはLoadFromFileまたはSaveToFileがないようです。)

PS:サンプルファイルはSkyDriveからダウンロードできます:REF_EncodedSample&REF_DecodedSample。(Zlibで圧縮された画像ファイル。)

procedure CompareBytes_2;
var
  ss_1: TStringStream;
  ss_2: TStringStream;
  sbytes_Read: TBytes;
  sbytes_Property: TBytes;
  len_sbytes_Read: Integer;
  len_sbytes_Property: Integer;
  filename: string;
begin
  filename := 'REF_EncodedSample';  // textual data
//  filename := 'REF_DecodedSample';  // non-textual data

  ss_1 := TStringStream.Create;
  ss_1.LoadFromFile(filename);
  ss_2 := TStringStream.Create;
  ss_2.LoadFromFile(filename);

  ss_1.SaveToFile(filename+ '_CopyByStringStream_1');
  ss_2.SaveToFile(filename+ '_CopyByStringStream_2');

  len_sbytes_Read := ss_1.Size;
  SetLength(sbytes_Read, len_sbytes_Read);
  ss_1.Read(sbytes_Read[0], len_sbytes_Read);

  sbytes_Property := ss_2.Bytes;

  ShowMessage(
    BoolToStr(
      Length(sbytes_Read) = Length(sbytes_Property),
      True));

  ShowMessage(
    BoolToStr(
      sbytes_Read[len_sbytes_Read - 1] = sbytes_Property[len_sbytes_Read - 1],
      True));

  ss_1.Free;
  ss_2.Free;
end;
4

2 に答える 2

5

文字列ストリームのドキュメントには次のように記載されています。

Bytesプロパティは、データが格納されているバッファを返します。Sizeプロパティを使用して、バッファ内の実際のデータ量を検索します。

おそらく、バッファは実際に必要なスペースよりも多くのスペースを保持するために割り当てられています。バッファの最初のサイズバイトのみに有効なコンテンツが含まれています。


また、SetLengthの呼び出し後、Length(sbytes_Read)は変更されないため、ss_1.Readの呼び出しは少し無意味です。また、ストリームから読み取る場合は、ReadではなくReadBufferを使用する必要があります。WriteBufferについても同様です。

于 2012-07-05T22:12:56.797 に答える
4

プロパティが使用するメモリ内の同じオブジェクトから読み取るため、プロパティにRead()あるものとは異なるバイトを返すことはできません。BytesRead()TBytesBytes

D2009 +では、TStringStreamTBytesStreamから派生するように変更され、TBytesStreamはから派生しTMemoryStreamます。そのため、現在、メソッドTStringStreamが利用可能です。以前のバージョンでは、代わりに直接派生しました。 以前のバージョンとは異なり、エンコードされたバイトを格納するようになりました。コンストラクターは入力としてを受け取り、指定されたものを使用してそれをにエンコードします(ここで、を指定しない場合は使用されます)。プロパティゲッターは、コンストラクターで指定されたを使用して、同じものをデコードします。andメソッドは、エンコード/デコードをまったく実行せずに、そのままロード/保存します。LoadFromFile()SaveToFile()TStringStreamTStreamTStringStreamStringTStringStreamStringTBytesTEncodingTEncoding.DefaultTEncodingDataStringTBytesStringTEncodingLoadFromFile()SaveToFile()TBytes

したがって、を呼び出すとLoadFromFile()、ファイルデータがそのままストリームに保存されます。TEncodingそのデータのエンコードがコンストラクターに渡されるエンコードと一致しない場合、DataStreamプロパティはガベージを返しますが、BytesプロパティとRead()メソッドは問題なく機能します。

問題は、プロパティがデータストレージに割り当てる Bytesメモリブロック全体を返すことを考慮していないことです。デルタに基づいてメモリをチャンクに割り当てるため、実際に必要な数よりも多くのメモリを割り当てることができます。そのため、個別のプロパティがあります。プロパティは割り当てられたメモリの合計サイズを示し、プロパティは割り当てられたメモリに格納されているバイト数を示します。を呼び出すと、ほとんどの場合、プロパティはロードされたファイルのサイズよりも大きくなります。TMemoryStreamTMemoryStreamCapacitySizeCapacitySizeLoadFromFile()Bytes

つまり、基本的に、コードはことわざの「リンゴ」と「オレンジ」を比較しているため、悪い結果が得られます。Capacityとプロパティの違いを説明するために、それに応じてコードを修正する必要がありSizeます。TBytes2つの変数の内容は、バイトまで同じになりSizeます。あなたはそれ以上を比較しているので、あなたのコードは失敗しています。

于 2012-07-05T22:53:32.190 に答える