How to use LZMA SDK to compress/decompress in Java

后端 未结 6 1054
灰色年华
灰色年华 2020-12-04 17:03

http://www.7-zip.org/sdk.html This site provide a LZMA SDK for compress/decompress files, I would like to give it a shot but I am lost.

Anyone got experience on this

相关标签:
6条回答
  • 2020-12-04 17:28

    You can use this library instead. It is "outdated" but still works fine.

    Maven dependency

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

    Utility class

    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);
            }
        }
    }
    

    Firstly you have to create a file with content to start compressing. You can use this website to generate random text.

    Example compression and decompression

    Path rawFile = Paths.get("raw.txt");
    Path compressedFile = Paths.get("compressed.lzma");
    
    LzmaCompressor lzmaCompressor = new LzmaCompressor(rawFile, compressedFile);
    lzmaCompressor.compress();
    lzmaCompressor.decompress();
    
    0 讨论(0)
  • 2020-12-04 17:31

    Use J7Zip. Its a java port of the LZMA SDK. You find it here:

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

    alternative

    Use the lzmajio.jar with LzmaInputStream and LzmaOutputStream classes

    you find it on github:

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

    0 讨论(0)
  • 2020-12-04 17:32

    Short answer: don't

    The 7zip sdk is old and unmaintained and it's just a JNI wrapper around the C++ library. A pure Java implementation on a modern JVM (1.7+) is as fast as a C++ one and has less dependecies and portability issues.

    Have a look at http://tukaani.org/xz/java.html

    XZ is a file format based on LZMA2 (an improved version of LZMA)

    The guys that invented the XZ format build a pure java implementation of the XZ archive compression / extraction algorithms

    The XZ file format is designed to store 1 file only. Thus you need to zip/tar the source folder(s) into a single uncompressed file first.

    Using the java library is as easy as this:

    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();
    
    0 讨论(0)
  • 2020-12-04 17:32

    Here are tested examples of using XZ Utils pure java library to pack and unpack XZ archives with LZMA2 compression algorithm with great ratio.

    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);
        }
    }
    
    0 讨论(0)
  • 2020-12-04 17:40

    Check out the LzmaAlone.java and LzmaBench.java files in the Java/SevenZip folder of the zip file from that link you posted.

    0 讨论(0)
  • 2020-12-04 17:41

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

    Kotlin code for Android:

     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 code:

     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);
        }
    
    0 讨论(0)
提交回复
热议问题