1

使用 TStringStream,bytesusing 其Bytes属性与bytes提取的 using不同TStream.Read。如下所示:

  1. bytes提取的usingTStream.Read代表正确的数据。
  2. 使用bytesBytes属性包含更多数据。(正确的最后一个字节与错误的最后一个字节bytes不同bytes

你能帮忙评论一下可能的原因吗?非常感谢您的帮助!

PS:Delphi XE,Windows 7。(似乎 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 属性查找缓冲区中的实际数据量。

据推测,缓冲区已被分配以容纳比实际需要更多的空间。只有缓冲区的第一个 Size 字节包含有效内容。


此外,对 ss_1.Read 的调用有点毫无意义,因为在调用 SetLength 后 Length(sbytes_Read) 不会改变。当从流中读取时,您将使用 ReadBuffer 而不是 Read。对于 WriteBuffer 也是如此。

于 2012-07-05T22:12:56.797 回答
4

不可能Read()返回与属性中的字节不同的字节Bytes,因为从属性使用的内存中的同一对象中Read()读取。TBytesBytes

在 D2009+ 中,TStringStream更改为从 TBytesStream 派生,而 TBytesStream 又从TMemoryStream. 这就是为什么TStringStreamhasLoadFromFile()SaveToFile()methods 现在可用的原因。在早期版本中,TStringStream直接派生自TStreamTStringStream现在存储编码字节,不像String在早期版本中那样。构造TStringStream函数将 aString作为输入并TBytes使用指定的将其编码为 a TEncodingTEncoding.Default如果您不指定 a ,则使用where TEncoding)。DataString属性 getter使用构造函数中指定的 将其解码TBytes回 a 。and方法按原样加载/保存,根本不执行任何编码/解码。StringTEncodingLoadFromFile()SaveToFile()TBytes

因此,如果您调用LoadFromFile(),它将按原样将文件数据存储在流中。TEncoding如果该数据的编码与传递给构造函数的编码不匹配,则该DataStream属性将返回垃圾,但该Bytes属性和该Read()方法将正常工作。

您的问题是您没有考虑到该属性返回为其数据存储分配 Bytes的整个内存块。基于增量以块的形式分配内存,因此它可能分配比实际需要更多的内存,这就是它具有单独和属性的原因。该属性表示已分配内存的总大小,而该属性表示已在分配的内存中存储了多少字节。当您调用 时,该属性几乎总是大于已加载文件的大小。TMemoryStreamTMemoryStreamCapacitySizeCapacitySizeLoadFromFile()Bytes

所以基本上,您的代码是将众所周知的“苹果”与“橙子”进行比较,这就是为什么您会得到不好的结果。Capacity您需要相应地修复您的代码,以说明和Size属性之间的差异。这两个TBytes变量的内容在 bytes 之前都是相同Size。您正在比较的不止这些,这就是您的代码失败的原因。

于 2012-07-05T22:53:32.190 回答