【问题标题】:How to use LZMA SDK to compress/decompress in JavaJava中如何使用LZMA SDK进行压缩/解压
【发布时间】:2011-07-25 18:53:12
【问题描述】:

http://www.7-zip.org/sdk.html 这个网站提供了一个用于压缩/解压缩文件的 LZMA SDK,我想试一试,但我迷路了。

有人有这方面的经验吗?还是教程?谢谢。

【问题讨论】:

标签: java 7zip lzma


【解决方案1】:

https://mvnrepository.com/artifact/org.tukaani/xz/1.8

Android 的 Kotlin 代码:

 fun initDatabase() {
    var gisFile = this.getDatabasePath("china_gis.db");
    if (!gisFile.exists()) {
        if(!gisFile.parentFile.exists()) gisFile.parentFile.mkdirs();
        var inStream = assets.open("china_gis_no_poly.db.xz")
        inStream.use { input ->
            val buf = ByteArray(1024)
            XZInputStream(input).use { input ->
                FileOutputStream(gisFile,true).use { output ->
                    var size: Int
                    while (true) {
                        size = input.read(buf);
                        if (size != -1) {
                            output.write(buf, 0, size)
                        } else {
                            break;
                        }
                    }
                    output.flush()
                }

            }
        }
    }
}

Java 代码:

 byte[] buf = new byte[8192];
    String name =  "C:\\Users\\temp22\\Downloads\\2017-007-13\\china_gis_no_poly.db.xz";
    try {

      InputStream input = new FileInputStream(name);
                FileOutputStream output=  new FileOutputStream(name+".db");
                try {
                    // Since XZInputStream does some buffering internally
                    // anyway, BufferedInputStream doesn't seem to be
                    // needed here to improve performance.
                    // in = new BufferedInputStream(in);
                    input = new XZInputStream(input);

                    int size;
                    while ((size = input.read(buf)) != -1)
                        output.write(buf, 0, size);
                    output.flush();

                } finally {
                    // Close FileInputStream (directly or indirectly
                    // via XZInputStream, it doesn't matter).
                    input.close();
                    output.close();
                }

    } catch (FileNotFoundException e) {
        System.err.println("XZDecDemo: Cannot open " + name + ": "
                           + e.getMessage());
        System.exit(1);

    } catch (EOFException e) {
        System.err.println("XZDecDemo: Unexpected end of input on "
                           + name);
        System.exit(1);

    } catch (IOException e) {
        System.err.println("XZDecDemo: Error decompressing from "
                           + name + ": " + e.getMessage());
        System.exit(1);
    }

【讨论】:

    【解决方案2】:

    这里是使用XZ Utils纯java库以LZMA2压缩算法压缩和解压XZ档案的测试示例。

    import org.tukaani.xz.*;
    
    // CompressXz
    public static void main(String[] args) throws Exception {
        String from = args[0];
        String to = args[1];
        try (FileOutputStream fileStream = new FileOutputStream(to);
             XZOutputStream xzStream = new XZOutputStream(
                     fileStream, new LZMA2Options(LZMA2Options.PRESET_MAX), BasicArrayCache.getInstance())) {
    
            Files.copy(Paths.get(from), xzStream);
        }
    }
    
    // DecompressXz
    public static void main(String[] args) throws Exception {
        String from = args[0];
        String to = args[1];
        try (FileInputStream fileStream = new FileInputStream(from);
             XZInputStream xzStream = new XZInputStream(fileStream, BasicArrayCache.getInstance())) {
    
            Files.copy(xzStream, Paths.get(to), StandardCopyOption.REPLACE_EXISTING);
        }
    }
    
    // DecompressXzSeekable (partial)
    public static void main(String[] args) throws Exception {
        String from = args[0];
        String to = args[1];
        int offset = Integer.parseInt(args[2]);
        int size = Integer.parseInt(args[3]);
        try (SeekableInputStream fileStream = new SeekableFileInputStream(from);
             SeekableXZInputStream xzStream = new SeekableXZInputStream(fileStream, BasicArrayCache.getInstance())) {
    
            xzStream.seek(offset);
            byte[] buf = new byte[size];
            if (size != xzStream.read(buf)) {
                xzStream.available(); // let it throw the last exception, if any
                throw new IOException("Truncated stream");
            }
            Files.write(Paths.get(to), buf);
        }
    }
    

    【讨论】:

      【解决方案3】:

      您可以改用this 库。它“过时”但仍然可以正常工作。

      Maven 依赖项

      <dependency>
          <groupId>com.github.jponge</groupId>
          <artifactId>lzma-java</artifactId>
          <version>1.2</version>
      </dependency>
      

      实用类

      import lzma.sdk.lzma.Decoder;
      import lzma.streams.LzmaInputStream;
      import lzma.streams.LzmaOutputStream;
      import org.apache.commons.compress.utils.IOUtils;
      
      import java.io.*;
      import java.nio.file.Path;
      
      public class LzmaCompressor
      {
          private Path rawFilePath;
          private Path compressedFilePath;
      
          public LzmaCompressor(Path rawFilePath, Path compressedFilePath)
          {
              this.rawFilePath = rawFilePath;
              this.compressedFilePath = compressedFilePath;
          }
      
          public void compress() throws IOException
          {
              try (LzmaOutputStream outputStream = new LzmaOutputStream.Builder(
                      new BufferedOutputStream(new FileOutputStream(compressedFilePath.toFile())))
                      .useMaximalDictionarySize()
                      .useMaximalFastBytes()
                      .build();
                   InputStream inputStream = new BufferedInputStream(new FileInputStream(rawFilePath.toFile())))
              {
                  IOUtils.copy(inputStream, outputStream);
              }
          }
      
          public void decompress() throws IOException
          {
              try (LzmaInputStream inputStream = new LzmaInputStream(
                      new BufferedInputStream(new FileInputStream(compressedFilePath.toFile())),
                      new Decoder());
                   OutputStream outputStream = new BufferedOutputStream(
                           new FileOutputStream(rawFilePath.toFile())))
              {
                  IOUtils.copy(inputStream, outputStream);
              }
          }
      }
      

      首先,您必须创建一个包含内容的文件才能开始压缩。您可以使用this网站生成随机文本。

      压缩和解压缩示例

      Path rawFile = Paths.get("raw.txt");
      Path compressedFile = Paths.get("compressed.lzma");
      
      LzmaCompressor lzmaCompressor = new LzmaCompressor(rawFile, compressedFile);
      lzmaCompressor.compress();
      lzmaCompressor.decompress();
      

      【讨论】:

        【解决方案4】:

        简短回答:不要

        7zip sdk 旧且未维护,它只是 C++ 库的 JNI 包装器。现代 JVM (1.7+) 上的纯 Java 实现与 C++ 一样快,并且依赖性和可移植性问题更少。

        看看http://tukaani.org/xz/java.html

        XZ是一种基于LZMA2(LZMA的改进版)的文件格式

        发明 XZ 格式的人构建了 XZ 存档压缩/提取算法的纯 java 实现

        XZ 文件格式旨在仅存储 1 个文件。因此,您需要先将源文件夹压缩/tar 为单个未压缩文件。

        使用java库就这么简单:

        FileInputStream inFile = new FileInputStream("src.tar");
        FileOutputStream outfile = new FileOutputStream("src.tar.xz");
        
        LZMA2Options options = new LZMA2Options();
        
        options.setPreset(7); // play with this number: 6 is default but 7 works better for mid sized archives ( > 8mb)
        
        XZOutputStream out = new XZOutputStream(outfile, options);
        
        byte[] buf = new byte[8192];
        int size;
        while ((size = inFile.read(buf)) != -1)
           out.write(buf, 0, size);
        
        out.finish();
        

        【讨论】:

        • 你能解释一下你的简短回答吗?
        • 这是一个相当古老的答案,我建议的库可能已被更新/更好的东西所取代。它的要点是 7zip sdk 是旧的和未维护的,它只是 C++ 库的 JNI 包装器。现代 JVM (1.7+) 上的纯 Java 实现与 C++ 一样快,并且具有较少的依赖性和可移植性问题。只是我的 2 美分。
        • 你说得对,在 Sun/Oracle JVM 上它和 C++ 一样快。不幸的是,在 Android 上,这种类型的操作仍然慢 5 到 10 倍(即使在带有 ART 的 Android 6 上)。这很令人沮丧。
        • 我的回答中有更多关于这个库的例子:stackoverflow.com/a/49454898/603516
        【解决方案5】:

        使用 J7Zip。它是 LZMA SDK 的 Java 端口。你可以在这里找到它:

        http://sourceforge.net/projects/p7zip/files/J7Zip/

        另类

        将 lzmajio.jar 与 LzmaInputStream 和 LzmaOutputStream 类一起使用

        你可以在 github 上找到它:

        http://github.com/league/lzmajio/downloads

        【讨论】:

          【解决方案6】:

          从您发布的链接中查看 zip 文件的 Java/SevenZip 文件夹中的 LzmaAlone.java 和 LzmaBench.java 文件。

          【讨论】:

          • 我不明白,他们不应该为此制作一个 javadoc 吗?
          • 是的,他们应该制作一些文档(或 javadoc),但有时您必须查看示例代码,这是我指导您的。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多