代码之家  ›  专栏  ›  技术社区  ›  Robbie Dee

将Java的DEFLATE算法移植到C#

  •  -2
  • Robbie Dee  · 技术社区  · 7 年前

    我们需要使用DEFLATE算法对Java系统创建的一些数据进行解压缩。这是我们无法控制的。

    虽然我们不知道确切的变体,但我们可以使用以下Java代码解压缩发送给我们的数据:

     public static String inflateBase64(String base64)
        {
            try (Reader reader = new InputStreamReader(
                    new InflaterInputStream(
                            new ByteArrayInputStream(
                                    Base64.getDecoder().decode(base64)))))
            {
                StringWriter sw = new StringWriter();
                char[] chars = new char[1024];
                for (int len; (len = reader.read(chars)) > 0; )
                    sw.write(chars, 0, len);
                return sw.toString();
            }
            catch (IOException e)
            {
                System.err.println(e.getMessage());
                return "";
            }
        }
    

    不幸的是,我们的生态系统是以碳为基础的。目前我们正在使用Process对象开发Java程序,但从性能角度来看,这显然是次优的,因此如果可能的话,我们希望将上述代码移植到C#。

    一些示例输入和输出:

    >java -cp . Deflate -c "Pack my box with five dozen liquor jugs."
    eJwLSEzOVsitVEjKr1AozyzJUEjLLEtVSMmvSs1TyMksLM0vUsgqTS/WAwAm/w6Y
    >java -cp . Deflate -d eJwLSEzOVsitVEjKr1AozyzJUEjLLEtVSMmvSs1TyMksLM0vUsgqTS/WAwAm/w6Y
    Pack my box with five dozen liquor jugs.
    >
    

    我们被告知Java系统符合 RFC 1951 因此,我们已经查看了相当多的库,但它们似乎都没有正确地解压缩数据(如果有的话)。DotNetZip就是一个例子:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Ionic.Zlib;
    
    namespace Decomp
    {
        class Program
        {
            static void Main(string[] args)
            {                        
                // Deflate
    
                String start = "Pack my box with five dozen liquor jugs.";
    
                var x = DeflateStream.CompressString(start);
                var res1 = Convert.ToBase64String(x, 0, x.Length);
    
                // Inflate 
    
                //String source = "eJwLSEzOVsitVEjKr1AozyzJUEjLLEtVSMmvSs1TyMksLM0vUsgqTS/WAwAm/w6Y"; // *** FAILS ***
                String source = "C0hMzlbIrVRIyq9QKM8syVBIyyxLVUjJr0rNU8jJLCzNL1LIKk0v1gMA"; 
    
                var part1 = Convert.FromBase64String(source);            
    
                var res2 =  DeflateStream.UncompressString(part1);
            }
        }
    }
    

    根据文档,这实现了RFC1951,但没有正确地破译字符串(可能是由于实现之间的细微算法差异)。

    从开发的角度来看,我们可以理解我们需要编写的确切变体。是否有任何标题信息或在线工具可用于提供初始转向?感觉就像我们在黑暗中拍摄一样。

    1 回复  |  直到 7 年前
        1
  •  3
  •   Vladimir P.    7 年前

    https://www.nuget.org/packages/ICSharpCode.SharpZipLib.dll/

    using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
    using System;
    using System.IO;
    using System.Text;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static void Main(string[] args)
            {
                string input = "Pack my box with five dozen liquor jugs.";
    
                string encoded = Encode(input);
                string decoded = Decode(encoded);
    
                Console.WriteLine($"Input: {input}");
                Console.WriteLine($"Encoded: {encoded}");
                Console.WriteLine($"Decoded: {decoded}");
    
                Console.ReadKey(true);
            }
    
            static string Encode(string text)
            {
                byte[] bytes = Encoding.UTF8.GetBytes(text);
    
                using (MemoryStream inms = new MemoryStream(bytes))
                {
                    using (MemoryStream outms = new MemoryStream())
                    {
                        using (DeflaterOutputStream dos = new DeflaterOutputStream(outms))
                        {
                            inms.CopyTo(dos);
    
                            dos.Finish();
    
                            byte[] encoded = outms.ToArray();                                              
    
                            return Convert.ToBase64String(encoded);
                        }
                    }
                }
            }
    
            static string Decode(string base64)
            {
                byte[] bytes = Convert.FromBase64String(base64);
    
                using (MemoryStream ms = new MemoryStream(bytes))
                {
                    using (InflaterInputStream iis = new InflaterInputStream(ms))
                    {
                        using (StreamReader sr = new StreamReader(iis))
                        {
                            return sr.ReadToEnd();
                        }
                    }
                }
            }
        }
    }