简体   繁体   English

将 Java 的 DEFLATE 算法移植到 C#

[英]Porting Java's DEFLATE algorithm to C#

We have a requirement to decompress some data created by a Java system using the DEFLATE algorithm.我们需要使用 DEFLATE 算法解压缩 Java 系统创建的一些数据。 This we have no control over.这是我们无法控制的。

While we don't know the exact variant, we are able to decompress data sent to us using the following Java code:虽然我们不知道确切的变体,但我们可以使用以下 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 "";
        }
    }

Unfortunately, our ecosystem is C# based.不幸的是,我们的生态系统是基于 C# 的。 We're shelling out to the Java program at the moment using the Process object but this is clearly sub-optimal from a performance point of view so we'd like to port the above code to C# if at all possible.我们目前正在使用 Process 对象对 Java 程序进行炮击,但从性能的角度来看,这显然是次优的,因此如果可能的话,我们希望将上述代码移植到 C#。

Some sample input and output:一些示例输入和输出:

>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.
>

We're told the Java system conforms to RFC 1951 so we've looked at quite a few libraries but none of them seem to decompress the data correctly (if at all).我们被告知 Java 系统符合RFC 1951,因此我们查看了很多库,但它们似乎都没有正确解压缩数据(如果有的话)。 One example is DotNetZip:一个例子是 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);
        }
    }
}

This implements RFC 1951 according to the documentation, but does not decipher the string correctly (presumably due to subtle algorithm differences between implementations).这根据文档实现了 RFC 1951,但没有正确解密字符串(大概是由于实现之间的细微算法差异)。

From a development point of view we could do with understanding the exact variant we need to write.从开发的角度来看,我们可以理解我们需要编写的确切变体。 Is there any header information or online tools we could use to provide an initial steer?是否有任何标题信息或在线工具可以用来提供初始引导? It feels like we're shooting in the dark a little bit here.感觉我们在这里有点在黑暗中拍摄。

https://www.nuget.org/packages/ICSharpCode.SharpZipLib.dll/ 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();
                    }
                }
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM