在Delphi中解压缩DeflateStream(C#) [英] Decompress DeflateStream (C#) in Delphi

查看:66
本文介绍了在Delphi中解压缩DeflateStream(C#)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序中,我构建了一个xml结构并将其发送到delphi客户端.在该xml的标签中,我有一个压缩的base64编码字符串:

in my application i build a xml structure an send it to a delphi client. In a tag of that xml i have a zipped, base64 coded string:

public static string Zip(string text)
    {
        byte[] buffer = System.Text.Encoding.Unicode.GetBytes(text);
        MemoryStream ms = new MemoryStream();
        //using (System.IO.Compression.GZipStream zip = new System.IO.Compression.GZipStream(ms, System.IO.Compression.CompressionMode.Compress, true))
        //{
        //    zip.Write(buffer, 0, buffer.Length);
        //}

        using (System.IO.Compression.DeflateStream zip = new System.IO.Compression.DeflateStream(ms, System.IO.Compression.CompressionMode.Compress, true))
        {
            zip.Write(buffer, 0, buffer.Length);
        }

        ms.Position = 0;
        MemoryStream outStream = new MemoryStream();

        byte[] compressed = new byte[ms.Length];
        ms.Read(compressed, 0, compressed.Length);

        byte[] gzBuffer = new byte[compressed.Length + 4];
        System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
        System.Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);
        return Convert.ToBase64String(gzBuffer);
    }

我的Delphi客户端必须从该标记获取数据,然后再次将其转换为基字符串.不幸的是,我得到了

My Delphi client has to get the data from that tag and turn it into the basestring again. unfortunately, i get a

ezdecompressionerror数据错误

ezdecompressionerror data error

我尝试了互联网提供的一些功能,例如:

I tried some of the functions the internet provides, e.g.:

function ZDecompressString(aText: string): string;
  var
  Utf8Stream: TStringStream;
  Compressed: TMemoryStream;
  Base64Stream: TStringStream;
begin
  Base64Stream := TStringStream.Create(aText, TEncoding.ASCII);
  try
    Compressed := TMemoryStream.Create;
    try
      DecodeStream(Base64Stream, Compressed);
      Compressed.Position := 0;
      Utf8Stream := TStringStream.Create('', TEncoding.ANSI);
      try
        ZDecompressStream(Compressed, Utf8Stream);
        Result := Utf8Stream.DataString;
      finally
        Utf8Stream.Free;
      end;
    finally
      Compressed.Free;
    end;
  finally
    Base64Stream.Free;
  end;
end;

但是这里没有任何作用.我正在使用XE2和标准的Zlib库.我通读了一些文章,但无法弄清楚:

But nothing worked here. I am using XE2 and the standard Zlib library. I read through some articles but i cant figure something out:

http://forum.codecall.net/topic/76077-zlib-library进行压缩和解压缩/

http://www.yanniel.info/2011/01/string-compress-decompress-delphi-zlib.html

Delphi XE和ZLib问题

http://www.delphipraxis.net/89090-string-mit-gzip-ent-zippen.html

我也尝试在c#中解压缩它,而不应该怀疑它是否有效.我想我的问题出在delphi减压代码的精通上,或者我是一个真正的愚蠢的人.但不幸的是,我不知道如何进行这项工作.:[

I also tried decompressing it in c# and should not suprise that it worked. I guess my problem lies at the udnerstanding of the delphi decompression code or maybe i am a real dumb person. But unfortunately i dont get it how i can make this work. :[

TIA

推荐答案

我将重新编写两个代码块.我建议您使用UTF-8作为编码.对于大多数西方文字,这是最节省空间的Unicode编码.

I'm going to re-write both blocks of code. I suggest that you use UTF-8 as your encoding. For most western text it is the most space efficient Unicode encoding.

C#代码如下:

using System;
using System.IO;
using System.IO.Compression;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        public static string Zip(string text)
        {
            byte[] utf8bytes = System.Text.Encoding.UTF8.GetBytes(text);
            MemoryStream compressedStream = new MemoryStream();
            using (var gzipStream = new GZipStream(compressedStream, 
                CompressionMode.Compress, true))
            {
                gzipStream.Write(utf8bytes, 0, utf8bytes.Length);
            }

            compressedStream.Position = 0;
            byte[] deflated = new byte[compressedStream.Length];
            compressedStream.Read(deflated, 0, (int)compressedStream.Length);
            return Convert.ToBase64String(deflated);
        }

        static void Main(string[] args)
        {
            Console.WriteLine(Zip("fubar"));
            Console.ReadLine();
        }
    }
}

哪个产生以下输出:


H4sIAAAAAAAEAEsrTUosAgDmcA8FBQAAAA==

我基本上保留了与您使用的相同的代码,但是切换到UTF-8并简化了代码,删除了一些不必要的步骤.我还删除了压缩缓冲区长度的写法.我认为没有必要这样做,无论如何它都不尊重网络字节顺序.

I've kept essentially the same code that you used, but switch to UTF-8 and streamlined the code removing some unnecessary steps. I've also removed the writing of the compressed buffer length. I don't see the need for that, and in any case it did not respect network byte order.

更重要的是,我切换到GZIP,因为在Delphi代码中更容易阅读.使用deflate会迫使您进入原始的zlib编程,这有点混乱.使用GZIP将GZIP标头添加到压缩流中.

More importantly I switched to GZIP because it's easier to read that in Delphi code. Using deflate forces you into raw zlib programming which is a bit messy. Using GZIP adds a GZIP header to the compressed stream.

在Delphi端,代码如下:

On the Delphi side the code looks like this:

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.Classes,
  System.ZLib,
  Soap.EncdDecd;

function Unzip(const zipped: string): string;
var
  DecompressionStream: TDecompressionStream;
  Compressed: TBytesStream;
  Decompressed: TStringStream;
begin
  Compressed := TBytesStream.Create(DecodeBase64(AnsiString(zipped)));
  try
    // window bits set to 15 + 16 for gzip
    DecompressionStream := TDecompressionStream.Create(Compressed, 15 + 16);
    try
      Decompressed := TStringStream.Create('', TEncoding.UTF8);
      try
        Decompressed.LoadFromStream(DecompressionStream);
        Result := Decompressed.DataString;
      finally
        Decompressed.Free;
      end;
    finally
      DecompressionStream.Free;
    end;
  finally
    Compressed.Free;
  end;
end;

procedure Main;
begin
  Writeln(Unzip('H4sIAAAAAAAEAEsrTUosAgDmcA8FBQAAAA=='));
end;

begin
  try
    Main;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

当然,对于较小的字符串,压缩开销和GZIP标头表示这不是压缩.加上base64编码后,压缩后+编码的字符串要比输入长得多.

Of course, for small strings the compression overhead and the GZIP header means that this is not compression. Coupled with base64 encoding the compressed + encoded string is much longer than the input.

但是我假设您希望发送大量文本,在这种情况下,GZIP标头将不重要.

I'm presuming however, that you wish to send large amounts of text, in which case the GZIP header will not be significant.

这篇关于在Delphi中解压缩DeflateStream(C#)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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