Delphi XE和ZLib问题 [英] Delphi XE and ZLib Problems

查看:1069
本文介绍了Delphi XE和ZLib问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Delphi XE,我有一些问题与ZLib例程...

I'm in Delphi XE and I'm having some problems with ZLib routines...

我试图压缩一些字符串(并将其编码)

I'm trying to compress some strings (and encode it to send it via a SOAP webservice -not really important-)

ZDecompressString的字符串结果在ZCompressString中有所不同。

The string results from ZDecompressString differs used in ZCompressString.

example1:

uses ZLib;
// compressing string
// ZCompressString('1234567890', zcMax); 
// compressed string ='xÚ3426153·°4'

// Uncompressing the result of ZCompressString, don't return the same:
// ZDecompressString('xÚ3426153·°4'); 
// uncompressed string = '123456789'

if '1234567890' <> ZDecompressString(ZCompressString('1234567890', zcMax)) then
  ShowMessage('Compression/Decompression fails');

example2:

Uses ZLib;
// compressing string
// ZCompressString('12345678901234567890', zcMax) 
// compressed string ='xÚ3426153·°40„³'

// Uncompressing the result of ZCompressString, don't return the same:
// ZDecompressString('xÚ3426153·°40„³') 
// uncompressed string = '12345678901'

if '12345678901234567890' <> ZDecompressString(ZCompressString('12345678901234567890', zcMax)) then
  ShowMessage('Compression/Decompression fails');

使用的函数来自一些关于压缩和解压缩的其他帖子

the functions used are from some other posts about compressing and deCompressing

function TForm1.ZCompressString(aText: string; aCompressionLevel: TZCompressionLevel): string;
var
  strInput,
  strOutput: TStringStream;
  Zipper: TZCompressionStream;
begin
  Result:= '';
  strInput:= TStringStream.Create(aText);
  strOutput:= TStringStream.Create;
  try
    Zipper:= TZCompressionStream.Create(strOutput, aCompressionLevel);
    try
      Zipper.CopyFrom(strInput, strInput.Size);
    finally
      Zipper.Free;
    end;
    Result:= strOutput.DataString;
  finally
    strInput.Free;
    strOutput.Free;
  end;
end;

function TForm1.ZDecompressString(aText: string): string;
var
  strInput,
  strOutput: TStringStream;
  Unzipper: TZDecompressionStream;
begin
  Result:= '';
  strInput:= TStringStream.Create(aText);
  strOutput:= TStringStream.Create;
  try
    Unzipper:= TZDecompressionStream.Create(strInput);
    try
      strOutput.CopyFrom(Unzipper, Unzipper.Size);
    finally
      Unzipper.Free;
    end;
    Result:= strOutput.DataString;
  finally
    strInput.Free;
    strOutput.Free;
  end;
end;

我错了什么?

否则有相同的问题

推荐答案

像我所知的所有压缩代码一样,ZLib是一个二进制压缩算法。它不知道字符串编码。您需要为它提供要压缩的字节流。当你解压缩,你被给回回字节流。

ZLib, like all compression codes I know, is a binary compression algorithm. It knows nothing of string encodings. You need to supply it with byte streams to compress. And when you decompress, you are given back byte streams.

但是你正在使用字符串,因此需要在编码文本和字节流之间进行转换。 TStringStream 类在你的代码中做这项工作。在创建字符串流实例时,为其提供文本编码。

But you are working with strings, and so need to convert between encoded text and byte streams. The TStringStream class is doing that work in your code. You supply the string stream instance a text encoding when you create it.

只有您的代码不提供编码。因此使用默认的本地ANSI编码。这是第一个问题。这不是一个完整的Unicode编码。一旦你使用本地ANSI代码页之外的字符,链就会分解。

Only your code does not supply an encoding. And so the default local ANSI encoding is used. And here's the first problem. That is not a full Unicode encoding. As soon as you use characters outside your local ANSI codepage the chain breaks down.

在创建字符串流实例时通过提供编码来解决这个问题。将编码传递给 TStringStream 构造函数。一个合理的选择是 TEncoding.UTF8 。当在压缩器中创建 strInput 时,以及在解压缩器中创建 strOutput 时传递此值。

Solve that problem by supplying an encoding when you create string stream instances. Pass the encoding to the TStringStream constructor. A sound choice is TEncoding.UTF8. Pass this when creating strInput in the compressor, and strOutput in the decompressor.

现在,您面临的下一个更大的问题是,您的压缩数据在任何编码中可能不是有意义的字符串。如果您切换到使用 AnsiString 而不是 string ,您可能会使现有代码的工作方式。但这是一个相当脆弱的解决方案。

Now the next and bigger problem that you face is that your compressed data may not be a meaningful string in any encoding. You might make your existing code sort of work if you switch to using AnsiString instead of string. But it's a rather brittle solution.

从根本上说,你错误地将二进制数据当作文本。一旦你压缩你有二进制数据。我的建议是,你不要尝试解释压缩的二进制文本。将其保留为二进制。压缩到 TBytesStream 。并从 TBytesStream 解压缩。因此压缩器函数返回 TBytes ,解压缩器接收到同样的 TBytes

Fundamentally you are making the mistake of treating binary data as text. Once you compress you have binary data. My recommendation is that you don't attempt to interpret the compressed binary as text. Leave it as binary. Compress to a TBytesStream. And decompress from a TBytesStream. So the compressor function returns TBytes and the decompressor receives that same TBytes.

如果由于某种原因必须压缩为字符串,那么必须对压缩的二进制进行编码。使用base64。 EncdDecd单元可以为你做。

If, for some reason, you must compress to a string, then you must encode the compressed binary. Do that using base64. The EncdDecd unit can do that for you.

压缩程序的流程如下:string - > UTF-8 bytes - > compressed bytes - > base64 string。显然你逆转箭头来解压。

This flow for the compressor looks like this: string -> UTF-8 bytes -> compressed bytes -> base64 string. Obviously you reverse the arrows to decompress.

这篇关于Delphi XE和ZLib问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆