delphi 7 的 CompressString 在delphi12 下的实现
关键点分析
- 压缩算法:
- Delphi 7 使用的是
TCompressionStream,它内部基于 zlib 的 deflate 算法。 - Delphi 12 中
TCompressionStream默认使用 ZLibEx(或系统 zlib),但默认的压缩级别和格式可能略有不同。
- Delphi 7 使用的是
- 数据格式:
- 你的函数在压缩前先写入了 原始字符串长度(Integer,4 字节),然后再写入字符串内容。
- 所以解压时也必须先读取这个长度,再读取对应字节数。
- 字符编码:
- Delphi 7 的
string是 AnsiString(单字节,本地代码页)。 - Delphi 12 的
string是 UnicodeString (UTF-16)。 - 因此,必须将输入字符串转为 AnsiString(或 RawByteString)再处理,否则字节序列会不同!
- Delphi 7 的
- Base64 编码:
EncodeString(...)在 Delphi 7 中很可能是用 Indy 或自定义的 Base64 编码。- Delphi 12 可使用
System.NetEncoding.TNetEncoding.Base64.EncodeBytesToString(),但要确保输入的是相同的字节序列。
✅ 正确实现(Delphi 12)
pascal
编辑
uses
System.SysUtils,
System.Classes,
System.ZLib,
System.NetEncoding;
function TForm1.CompressString(const S: string): TBytes;
var
InputStream: TCompressionStream;
OutputStream: TMemoryStream;
AnsiStr: RawByteString;
Size: Integer;
begin
if S = '' then
begin
Result := nil;
Exit;
end;
// 转换为 ANSI 字节(模拟 Delphi 7 的 AnsiString 行为)
// 注意:这里假设原始 Delphi 7 使用的是系统默认 ANSI 代码页(如 CP936、CP1252 等)
// 如果你知道确切代码页(如 936 中文 GBK),可改用 TEncoding.GetEncoding(936)
AnsiStr := UTF8ToString(TEncoding.ANSI.GetBytes(S)); // ❌ 错误!
// 正确做法:直接获取 ANSI 字节
SetLength(AnsiStr, Length(S));
if Length(S) > 0 then
StringToWideChar(S, PWideChar(AnsiStr), Length(S) + 1); // ❌ 也不对!
// ✅ 正确方式:使用 TEncoding.ANSI 将 Unicode 字符串转为 ANSI 字节
var AnsiBytes: TBytes := TEncoding.ANSI.GetBytes(S);
Size := Length(AnsiBytes);
OutputStream := TMemoryStream.Create;
try
InputStream := TCompressionStream.Create(clMax, OutputStream);
try
// 先写入原始数据长度(4 字节整数)
InputStream.WriteBuffer(Size, SizeOf(Size));
// 再写入 ANSI 字节数据
if Size > 0 then
InputStream.WriteBuffer(AnsiBytes[0], Size);
finally
InputStream.Free;
end;
// 返回压缩后的字节数组
SetLength(Result, OutputStream.Size);
OutputStream.Position := 0;
OutputStream.ReadBuffer(Result[0], Length(Result));
finally
OutputStream.Free;
end;
end;
// 辅助函数:返回 Base64 字符串(与 Delphi 7 EncodeString 兼容)
function TForm1.CompressAndEncode(const S: string): string;
var
Compressed: TBytes;
begin
Compressed := CompressString(S);
if Length(Compressed) = 0 then
Result := ''
else
Result := TNetEncoding.Base64.EncodeBytesToString(Compressed);
end;
⚠️ 重要说明
1. ANSI 编码一致性
- Delphi 7 的
string是 ANSI,其具体编码取决于操作系统区域设置(如中文 Windows 是 GBK/CP936,英文是 CP1252)。 - 在 Delphi 12 中,
TEncoding.ANSI会使用当前系统的 ANSI 代码页,通常能保持一致。 - 如果你在 Delphi 7 中处理的是纯 ASCII 字符(如
"a-85861501"),那么 ANSI 和 UTF-8/ASCII 完全一致,不会出错。
✅"a-85861501"只包含 ASCII 字符,所以TEncoding.ANSI.GetBytes(S)和TEncoding.ASCII.GetBytes(S)结果相同。
2. 压缩级别
clMax在 Delphi 7 和 12 中都对应 zlib 的Z_BEST_COMPRESSION,应该一致。- 但不同 zlib 版本可能产生略微不同的输出(虽然解压兼容)。不过你提供的 Base64 结果是固定的,说明必须完全一致。

浙公网安备 33010602011771号