使用TStringStream时,使用bytes
属性的Bytes
与使用bytes
提取的TStream.Read
不同。如下图所示:
bytes
提取的TStream.Read
表示正确的数据。bytes
使用其Bytes
属性包含更多数据。 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;
答案 0 :(得分:5)
字符串流documentation表示:
Bytes属性返回存储数据的缓冲区。使用Size属性查找缓冲区中的实际数据量。
据推测,缓冲区已被分配用于容纳比实际需要更多的空间。只有缓冲区的第一个Size字节包含有效内容。
此外,对ss_1.Read的调用有点无意义,因为在调用SetLength之后Length(sbytes_Read)没有改变。从流中读取时,您将使用ReadBuffer而不是Read。同样适用于WriteBuffer。
答案 1 :(得分:4)
Read()
不可能返回与Bytes
属性不同的字节,因为Read()
从内存中的TBytes
对象读取Bytes
TStringStream
1}}属性使用。
在D2009 +中,TMemoryStream
被更改为从TBytesStream派生,而TBytesStream又派生自TStringStream
。这就是为什么LoadFromFile()
现在有SaveToFile()
和TStringStream
方法可用的原因。在早期版本中,TStream
直接来自TStringStream
。 String
现在存储编码的字节,而不像早期版本中那样存储TStringStream
。 String
构造函数将TBytes
作为输入,并使用指定的TEncoding
将其编码为TEncoding.Default
(如果您未指定{TEncoding
,则使用DataString
{1}})。 TBytes
属性getter使用构造函数中指定的String
将相同的TEncoding
解码回LoadFromFile()
。 SaveToFile()
和TBytes
方法按原样加载/保存LoadFromFile()
,而根本不执行任何编码/解码。
因此,如果您调用TEncoding
,它将按原样将文件数据存储在流中。如果该数据的编码与传递给构造函数的DataStream
不匹配,则Bytes
属性将返回垃圾,但Read()
属性和Bytes
方法会很好。
您的问题是您没有考虑TMemoryStream
属性返回TMemoryStream
为其数据存储分配的整个内存块。 Capacity
基于增量分配内存,因此它可以分配比实际需要更多的内存,这就是它具有单独的Size
和Capacity
属性的原因。 Size
属性指示已分配内存的总大小,而LoadFromFile()
属性指示已分配内存中已存储的字节数。当您调用Bytes
时,Capacity
属性几乎总是大于已加载文件的大小。
所以基本上,你的代码将众所周知的“苹果”与“橙子”进行比较,这就是为什么你会得到不好的结果。您需要相应地修改代码,以便考虑Size
和TBytes
属性之间的差异。两个Size
变量的内容将相同最多{{1}}个字节。您正在比较更多,这就是您的代码失败的原因。