我有这个方法,
var
s : TStringList;
fVar : string;
begin
s := TStringList.Create;
fVar := ZCompressStr('text');
ShowMessage( IntToStr(length(fVar) * SizeOf(Char)) );
//24
s.text := fVar;
ShowMessage( IntToStr( length(s.text) * SizeOf(Char)) );
//18
end;
ZCompressStr来自http://www.base2ti.com/zlib.htm,第121行改为 {$ ifndef UNICODE} 至 {$ ifdef UNICODE} 使它编译。</ p>
无论如何,如果我使用fVar变量,我可以调用ZDecompressStr,但是一旦我将它移动到字符串列表或备忘录,它似乎松开了那6个字节的数据....如果我尝试在s上使用ZDecompressStr .text var因缓冲区错误而失败。
答案 0 :(得分:14)
您没有理由不得不更改 ZLibEx.pas 的第121行;它适用于所有版本的Delphi,包括Delphi 2009. UNICODE
符号应仅为Delphi 2009定义,如果是,RawByteString
的类型定义,应该跳过UnicodeString
和UnicodeChar
,因为它们已经是语言中的内在类型。
ZCompressStr
将生成一个字符串,该字符串可能包含不可打印的字符,包括空字节。它将结果存储在RawByteString
中,Delphi专门处理它。
TStringList
,就像Delphi 2009中的其他所有内容一样,使用Unicode。其Text
属性的类型为UnicodeString
。当您将任何非UnicodeString
值分配给UnicodeString
时,您会获得转换,例如MultiByteToWideStr
API函数。即使RawByteString
也包含在该规则中。如果您尚未将特定于代码页的字符串值分配给RawByteString
,那么它将具有代码页0,即CP_ACP
,即系统的默认代码页。
如果字符串实际上不包含根据系统代码页编码的字符,那么任何转换都会出现问题:垃圾进入,垃圾进出。特别是,不能保证您将获得相同数量的字符。
As Smok1 mentioned,TStringList.Text
是一个属性。它有一个setter方法,将给定的字符串拆分为单独的行。当您读取属性时,它会再次将所有这些行重新连接成一个字符串。当设置属性时,TStrings.SetTextStr
(在 Classes.pas 中,如果您感到好奇)会在#0
出现任意一行时拆分该行, #10
或#13
。也就是说,空字符,换行符和回车符。重新连接所有行时,它将使用其LineBreak
属性,该属性使用全局sLineBreak
变量初始化。换行符也放在最后一个字符串之后,因此每一行都以LineBreak
结尾。因此,转换不一定是往返。
因此,有两点需要从中学到:
TStrings
个后代来保存您不想处理多个字符串的内容。另一个好建议:不要将string
用作通用数据存储类型。仅用于实际文本。要存储任意二进制数据,请选择TBytes
或TMemoryStream
。使用您的示例,您可以压缩这样的字符串:
var
ss: TStream;
ms: TMemoryStream;
begin
ss := TStringStream.Create('text');
try
ms := TMemoryStream.Create;
try
ShowMessage(IntToStr(ss.Size));
ZCompressStream(ss, ms);
ShowMessage(IntToStr(ms.Size));
finally
ms.Free;
end;
finally
ss.Free;
end;
end;
答案 1 :(得分:2)
这可能是转换--TStringList.Text属性是属性,而不是变量。您使用它有点危险,因为在TStringList中有一些Text处理。