delphi 7 的 CompressString 在delphi12 下的实现

关键点分析

  1. 压缩算法
    • Delphi 7 使用的是 TCompressionStream,它内部基于 zlib 的 deflate 算法。
    • Delphi 12 中 TCompressionStream 默认使用 ZLibEx(或系统 zlib),但默认的压缩级别和格式可能略有不同。
  2. 数据格式
    • 你的函数在压缩前先写入了 原始字符串长度(Integer,4 字节),然后再写入字符串内容。
    • 所以解压时也必须先读取这个长度,再读取对应字节数。
  3. 字符编码
    • Delphi 7 的 string 是 AnsiString(单字节,本地代码页)。
    • Delphi 12 的 string 是 UnicodeString (UTF-16)
    • 因此,必须将输入字符串转为 AnsiString(或 RawByteString)再处理,否则字节序列会不同!
  4. 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 结果是固定的,说明必须完全一致
posted @ 2026-01-21 16:11  Thenext  阅读(0)  评论(0)    收藏  举报