zoukankan      html  css  js  c++  java
  • 【项目分析】利用J#类库解决项目中数据压缩以及解压的问题

          在上一篇文章(利用C#改写JAVA中的Base64.DecodeBase64以及Inflater解码),我已经提到,目前的项目需要进行平台移植,即JAVA平台服务迁移到DotNet平台服务中,服务是用来和公司的一款终端设备产品进行数据传输与交换。

    image

    如图,这个终端产品用于与终端接口进行TCP对接。而终端接口(也就是我现在要讨论的平台服务)。

    1. 在上一篇文章中,我使用了ICSharpCode.SharpZipLib.dll组件,对于进行数据压缩以及解压,首先JAVA平台服务中利用log4j组件产生日志文件,查看其中一个日志文件的某一片段:

    image

    这个是终端设备通过JAVA平台服务请求一个商户信息时候,返回的一个HTTP反馈数据,可以看到HTTP反馈包包括两方面内容,一个是数据头,一个是数据体,数据体是一个base64的编码:

    eJwzMAADI3MgYWhgZGAIJIxMDY0NLQ0sjPQMEMDQVEFB4eyPrY+NjBTIAsGGRpYGBmZG5oZAky1I13/xwvZF1y5cOEKe7cQBAPx4Lgo=

    JAVA平台服务通过代码:

    String str = "……";
    new String(ZipUtil.decompressByteArray(Base64.decodeBase64(str.getBytes())));

    进行数据体解压。

    2. 在.NET中,我利用ICSharpCode.SharpZipLib组件进行数据体解压。

    解压方法为:

    解压代码
    private static string _Decompress(byte[] bytes) 

        string resultStr 
    = string.Empty; 
        using (MemoryStream memoryStream 
    = new MemoryStream(bytes)) 
        { 
            using (SharpZipLibStreams.InflaterInputStream stream 
    = new SharpZipLibStreams.InflaterInputStream(memoryStream)) 
            { 
                using (MemoryStream buffer 
    = new MemoryStream()) 
                { 
                    
    byte[] result = new byte[1024]; 

                    
    int resLen; 
                    
    while ((resLen = stream.Read(result, 0, result.Length)) > 0
                    { 
                        buffer.Write(result, 
    0, resLen); 
                    } 
                    
    byte[] byteDest = buffer.ToArray(); 
                    resultStr 
    = Encoding.Default.GetString(buffer.ToArray(), 0, byteDest.Length); 
                } 
            } 
        } 
        
    return resultStr; 
    }

    调用方法:

    string baseStr1 = "eJwzMAADI3MgYWhgZGAIJIxMDY0NLQ0sjPQMEMDQVEFB4eyPrY+NjBTIAsGGRpYGBmZG5oZAky1I13/xwvZF1y5cOEKe7cQBAPx4Lgo="

    string str1 = ZipUtil.Decompress(baseStr1, ZipType.SharpZipLib); 
    Console.WriteLine(str1);

    运行结果:

    image

    数据体解压后的数据是正确的。得出来的结果令我挺开心的,完成了第一步。

    那么好了,我现在想继续对这个字符串压缩,看能否得到刚才的BASE64编码字符串。

    压缩方法为:

    压缩代码
    private static byte[] _Compress(string str) 

        
    byte[] bytes = Encoding.Default.GetBytes(str); 

        
    using (MemoryStream memoryStream = new MemoryStream()) 
        { 
            
    using (SharpZipLibStreams.DeflaterOutputStream stream = new SharpZipLibStreams.DeflaterOutputStream(memoryStream)) 
            { 
                stream.Write(bytes, 
    0, bytes.Length); 
            } 
            
    return memoryStream.ToArray(); 
        } 
    }

    调用方法:

    string str2 = ZipUtil.Compress(str1, ZipType.SharpZipLib); 
    Console.WriteLine(str2);

    再运行结果:

    image

    发现这个字符串和原来的BASE64字符串的内容不一样。对于这个方法自己也折腾了挺久,始终无法得到正确的字符串。后来使用这个得出来的字符串,再进行解码,得到的也是以下的字符串:

    image

    PS:自己实在没有办法,如果大家有什么可以解决的办法,不凡告知我一下,谢谢大家!)

    3. 后来对于这个原始字符串进行了分析,首先我在VS2010下,编写测试代码:

               string s1 = "00000002700010201102251319082.0000000000015   网点22                                                      S1290062710828                                                  研发中心                                                                                            "
                
    byte[] bytes = Encoding.Default.GetBytes(s1); 
                
    for(int i = 0; i < bytes.Length; i++
                { 
                    Console.Write(bytes[i] 
    + ","); 
                }

    运行结果:

    image

    接着我在Eclipse平台下,编写代码:

    String s1 = "00000002700010201102251319082.0000000000015   网点22                                                      S1290062710828                                                  研发中心                                                                                            "
    byte[] b1 = s1.getBytes(); 
    for(int i = 0; i < b1.length; i++

        System.out.print(b1[i] 
    + ","); 
    }

    运行结果:

    image 

    为什么这里不一样呢?哦,问题就在这里,在JAVA中的byte类型,是有符号的整型类型,相当于C#中的sbyte类型。

    而C#中的byte是无符号的整型类型,它的范围为0-255之间,即无符号8位整数,因此相对于byte类型的sbyte类型,应当将byte的整型值全部减去256,请对比两张图,可以发现205-256=-51,满足了要求。

    但是对于ICSharpCode.SharpZipLib组件,没有方法可以对sbyte类型进行解压以及压缩操作。虽然通过分析ICSharpCode.SharpZipLib源代码,可以解决。但是这样让工作更复杂化。

    4. 最后,想起来了J#类库中包括对于JAVA类库的使用,这些类库是微软对于JAVA包的二次封装。(你可以通过安装VS2005获得这些包,也就是DLL,目录默认在:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727中),见如下:

    image

    如果你的开发环境没有安装VS2005,也没有关系,你可以把这里的DLL文件引用到你的项目中,主要引用vjslib.dll以及vjsnativ.dll,vjsnativ.dll是个COM组件,所以你可以把它的dll的属性修改设置:

    image

    这样你就可以在VS2010开发环境下使用具有JAVA包的C#类库。

    使用命名空间:

    using java.io; 
    using java.util.zip;

    压缩以及解压的代码如下:

    压缩代码:

    压缩代码
    private static sbyte[] _CompressString(string str) 

        Deflater f 
    = new Deflater(); 
        
    byte[] bs = Encoding.Default.GetBytes(str); 
        
    sbyte[] sBytes = ByteToSByte(bs); 

        f.setLevel(
    -1); 
        f.setInput(sBytes); 
        f.finish(); 

        ByteArrayOutputStream o 
    = new ByteArrayOutputStream(sBytes.Length); 
        
    try 
        { 
            
    sbyte[] buf = new sbyte[1024]; 
            
    while (!f.finished()) 
            { 
                
    int got = f.deflate(buf); 
                o.write(buf, 
    0, got); 
            } 
        } 
        
    finally 
        { 
            o.close(); 
        } 
        
    return o.toByteArray(); 
    }

    解压代码:

    解压代码
    public static string _DecompressString(sbyte[] sBytes) 

        Inflater f 
    = new Inflater(); 
        f.setInput(sBytes); 

        ByteArrayOutputStream o 
    = new ByteArrayOutputStream(sBytes.Length); 
        
    try 
        { 
            
    sbyte[] buf = new sbyte[1024]; 
            
    while (!f.finished()) 
            { 
                
    int got = f.inflate(buf); 
                o.write(buf, 
    0, got); 
            } 
        } 
        
    finally 
        { 
            o.close(); 
        } 

        
    byte[] decompessBytes = SByteToByte(o.toByteArray()); 

        
    return Encoding.Default.GetString(decompessBytes); 
    }

    调用方法:

    string baseStr1 = "eJwzMAADI3MgYWhgZGAIJIxMDY0NLQ0sjPQMEMDQVEFB4eyPrY+NjBTIAsGGRpYGBmZG5oZAky1I13/xwvZF1y5cOEKe7cQBAPx4Lgo="

    string str1 = ZipUtil.Decompress(baseStr1, ZipType.JSharp); 
    Console.WriteLine(str1); 

    string str2 = ZipUtil.Compress(str1, ZipType.JSharp); 
    Console.WriteLine(str2);

    运行结果:

    image

    从运行结果上看,最后得到的BASE64字符串与原来的BASE64字符串保持一致了。

          这样我就利用J#类库解决了项目中数据压缩以及解压的问题。有人可能要问我为什么要使用这样的一个解码规则呢?因为终端设备的程序已经固化在终端设备中了,它产生的HTTP数据头以及数据体,具有一定的规则,所以作为平台服务端,必须遵循这个规则来执行。

          本篇文章作为一个分析项目中一些问题的思路,希望能够给大家带来些帮助吧!

    附上本篇文章的源代码:JavaZipDemo.rar

  • 相关阅读:
    Django--URLconf
    Django--视图层
    Django 初识之安装下载以及模型目录简介
    jQuery基础
    BOM&DOM
    带你快速上手前端三剑客之css
    mysql 触发器、流程控制、事务等
    前端之html
    python中pymsql常用方法(1)
    18、设计模式-行为型模式-迭代器模式
  • 原文地址:https://www.cnblogs.com/liping13599168/p/1966919.html
Copyright © 2011-2022 走看看