Java C# LZMA 字符串压缩解压

本贴最后更新于 2935 天前,其中的信息可能已经渤澥桑田

压缩:将指定的原字符串用 LZMA 算法压缩,然后以 BASE64 编码
解压:将指定的 BASE64 编码的字符串用 LZMA 解压,返回原字符串

原字符串为 UTF-8 编码。

Java 版本

导入包

基本都是 JDK 内置的包,BASE64 部分可能需要替换一下(JDK8 已经自带 BASE64)。

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;

实现部分

/**
 * 使用 lzma 进行压缩.
 *
 * @param str 压缩前的文本
 * @return 压缩后的文本(BASE64 编码)
 * @throws IOException 如果解压异常
 */
public static String lzma(final String str) throws IOException {
    if (str == null || "".equals(str)) {
        return str;
    }

    final SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder();

    final ByteArrayOutputStream out = new ByteArrayOutputStream();
    final ByteArrayInputStream in = new ByteArrayInputStream(str.getBytes());

    try {
        encoder.SetEndMarkerMode(false);
        encoder.WriteCoderProperties(out);
        final long fileSize = in.available();
        for (int i = 0; i < 8; i++) {
            out.write((int) (fileSize >>> (8 * i)) & 0xFF);
        }
        encoder.Code(in, out, -1, -1, null);

        final byte[] compressed = out.toByteArray();

        return new String(Base64.encodeBase64(compressed), "UTF-8");
    } finally {
        IOUtils.closeQuietly(in);
        IOUtils.closeQuietly(out);
    }
}

/**
 * 使用 lzma 进行解压缩.
 *
 * @param compressedStr 压缩后的文本(BASE64 编码)
 * @return 解压后的文本
 * @throws IOException 如果解压异常
 */
public static String unlzma(final String compressedStr) throws IOException {
    if (null == compressedStr || "".equals(compressedStr)) {
        return compressedStr;
    }

    final SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();

    final ByteArrayOutputStream out = new ByteArrayOutputStream();
    final ByteArrayInputStream in = new ByteArrayInputStream(Base64.decodeBase64(compressedStr));

    try {
        final int propertiesSize = 5;
        final byte[] properties = new byte[propertiesSize];
        if (in.read(properties, 0, propertiesSize) != propertiesSize) {
            throw new IOException("input .lzma file is too short");
        }
        if (!decoder.SetDecoderProperties(properties)) {
            throw new IOException("Incorrect stream properties");
        }
        long outSize = 0;
        for (int i = 0; i < 8; i++) {
            final int v = in.read();
            if (v < 0) {
                throw new IOException("Can't read stream size");
            }
            outSize |= ((long) v) << (8 * i);
        }
        if (!decoder.Code(in, out, outSize)) {
            throw new IOException("Error in data stream");
        }

        return out.toString("UTF-8");
    } finally {
        IOUtils.closeQuietly(in);
        IOUtils.closeQuietly(out);
    }
}

C# 版本

命名空间

using System;
using System.Text;
using System.IO;
using SevenZip;

实现部分

/// <summary>
/// 使用 lzma 进行压缩
/// </summary>
/// <param name="str">压缩前的文本</param>
/// <returns>压缩后的文本(BASE64 编码)</returns>
public static string lzma(string str)
{
    if (null == str || "".Equals(str))
    {
        return str;
    }

    byte[] buffer = Encoding.UTF8.GetBytes(str);
    byte[] compressed = SevenZipHelper.Compress(buffer);

    return Convert.ToBase64String(compressed);
}

/// <summary>
/// 使用 lzma 进行解压缩
/// </summary>
/// <param name="compressedStr">压缩后的文本(BASE64 编码)</param>
/// <returns>解压后的文本</returns>
public static string unlzma(string compressedStr)
{
    if (null == compressedStr || "".Equals(compressedStr))
    {
        return compressedStr;
    }

    byte[] decompressed = SevenZipHelper.Decompress(Convert.FromBase64String(compressedStr));


    return Encoding.UTF8.GetString(decompressed);
}


public static class SevenZipHelper
{

    static int dictionary = 1 << 23;

    // static Int32 posStateBits = 2;
    // static  Int32 litContextBits = 3; // for normal files
    // UInt32 litContextBits = 0; // for 32-bit data
    // static  Int32 litPosBits = 0;
    // UInt32 litPosBits = 2; // for 32-bit data
    // static   Int32 algorithm = 2;
    // static    Int32 numFastBytes = 128;
    static bool eos = false;

    static CoderPropID[] propIDs =
                {
                CoderPropID.DictionarySize,
                CoderPropID.PosStateBits,
                CoderPropID.LitContextBits,
                CoderPropID.LitPosBits,
                CoderPropID.Algorithm,
                CoderPropID.NumFastBytes,
                CoderPropID.MatchFinder,
                CoderPropID.EndMarker
            };

    // these are the default properties, keeping it simple for now:
    static object[] properties =
                {
                (Int32)(dictionary),
                (Int32)(2),
                (Int32)(3),
                (Int32)(0),
                (Int32)(2),
                (Int32)(128),
                "bt4",
                eos
            };

    public static byte[] Compress(byte[] inputBytes)
    {
        MemoryStream inStream = new MemoryStream(inputBytes);
        MemoryStream outStream = new MemoryStream();
        SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder();
        encoder.SetCoderProperties(propIDs, properties);
        encoder.WriteCoderProperties(outStream);
        long fileSize = inStream.Length;
        for (int i = 0; i < 8; i++)
            outStream.WriteByte((Byte)(fileSize >> (8 * i)));
        encoder.Code(inStream, outStream, -1, -1, null);

        return outStream.ToArray();
    }

    public static byte[] Decompress(byte[] inputBytes)
    {
        MemoryStream newInStream = new MemoryStream(inputBytes);

        SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();

        newInStream.Seek(0, 0);
        MemoryStream newOutStream = new MemoryStream();

        byte[] properties2 = new byte[5];
        if (newInStream.Read(properties2, 0, 5) != 5)
            throw (new Exception("input .lzma is too short"));
        long outSize = 0;
        for (int i = 0; i < 8; i++)
        {
            int v = newInStream.ReadByte();
            if (v < 0)
                throw (new Exception("Can't Read 1"));
            outSize |= ((long)(byte)v) << (8 * i);
        }
        decoder.SetDecoderProperties(properties2);

        long compressedSize = newInStream.Length - newInStream.Position;
        decoder.Code(newInStream, newOutStream, compressedSize, outSize, null);

        byte[] b = newOutStream.ToArray();

        return b;
    }
}

姊妹篇: https://hacpai.com/article/1480569906672

  • LZMA
    1 引用 • 6 回帖
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3190 引用 • 8214 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • tomaer

    你总和 @yangyujiao 在论坛上这样搞,不怕 V 收拾你吗?

  • 其他回帖
  • 88250

    我就是网络搬运工 + 照猫画虎..

    1 回复
  • jonwinters

    弄个 Javascript 版本就好了

  • yangyujiao

    终于可以评论了
    你还会 C#呀。。。
    chrome 崩溃了 7 8 次····

    1 回复
  • 查看全部回帖