如何在安卓中使用XZ库压缩/解压文件

5

https://tukaani.org/xz/java.html这个网站提供了一个用于压缩/解压文件的XZ库,我想试一试,但是不知道该怎么做。

有人有经验吗?或者有教程可以参考吗?谢谢。


你可以在这里找到一个类似的教程,它使用gz,只需将GzipCompressorInputStream替换为XZCompressorInputStream即可。记得添加依赖项,就这些 :) https://dev59.com/pW3Xa4cB1Zd3GeqPiL0_#55736666 - Mia
3个回答

4

我最近使用了这个库,以下是我的Github链接中的工作代码XZ压缩算法。您可以在Android项目中使用此类。这是Main类,以便了解如何使用此类。

public static void main(String[] args){
  String input = "Some string blah blah blah";
  System.out.println("XZ or LZMA2 library.....");

  // If you are using some file instead of plain text you have to 
  //convert it to bytes here and pass it to `compress` method.

  byte[] xzCompressed = XZ_LZMA2.compress(input);
  System.out.println("Input length:" + input.length());
  System.out.println("XZ Compressed Length: "+ xzCompressed.length);
  String xzDecompressed = XZ_LZMA2.decompress(xzCompressed);
  System.out.println("XZ Decompressed : "+ xzDecompressed);

  // If you are using decompression for some compressed file instead of
  // plain text return bytes from `decompress` method and put it in 
  //FileOutputStream to get file back
}

注意: XZ压缩算法需要大量内存才能运行。 不建议在任何移动平台上使用,如Android。这将导致内存不足异常。Android提供了称为Deflater和InflaterZLIB压缩库。在Android平台上运行良好。


它给我一个内存不足的错误。有什么办法可以修复吗? - Saroj Raut
如果我能看到错误日志,那会很有帮助。 :) - Jai Prak

0

您可以使用Android AOSP中的XZ-Java静态库或'org.tukaani:xz:1.8'库来压缩XZ文件格式的文件。以下是可用于在XZ格式中压缩文件的工作代码。创建Asynctask以压缩多个文件并使用以下Java代码进行压缩。

Android.mk Changes for building in AOSP:
LOCAL_STATIC_JAVA_LIBRARIES := \
       xz-java
OR 

Gradle File Changes for building in Android Studio:
implementation 'org.tukaani:xz:1.8'

Java Code: 
public void CompressFile(String inputFile, String outputFile){
    XZOutputStream xzOStream = null;
        try {
            LZMA2Options opts = new LZMA2Options();
            opts.setPreset(7);

            FileOutputStream foStream = new FileOutputStream(outputFile);
            xzOStream = new XZOutputStream(foStream, opts);
            FileInputStream fiStream = new FileInputStream(inputFile);
            Scanner sc = null;

            try {
                sc = new Scanner(fiStream);
                while (sc.hasNextLine()) {
                    String line = sc.nextLine() + "\n";
                    xzOStream.write(line.getBytes(), 0, line.getBytes().length);
                }
                Utils.removeFile(inputFile);
            } finally {
                if (fiStream != null) {
                    fiStream.close();
                }

                if (sc != null) {
                    sc.close();
                }

                if(xzOStream != null)
                    xzOStream.close();

                if(foStream != null)
                    foStream.close();
            }
        }catch (Exception e){
            Log.e(TAG, "CompressFileXZ() Exception: " + e.toString());
        }
}

0
我的Android应用程序在启动时从其assets目录加载数据文件,我已经知道解压缩后的大小,所以我只需要编写以下内容:
byte[] data = new byte[ /* decompressed size here */ ];
new org.tukaani.xz.XZInputStream(context.getAssets().open("file.xz")).read(data);

然后执行git clone https://git.tukaani.org/xz-java.gitcp -r xz-java/src/org,将其复制到我的应用程序的src目录中(并确保所有.java文件都在我的javac命令行中被提及——我仍然使用老式的命令行脚本来编译我的应用程序;我还没有为Android Studio或Gradle设置它们)。 然而,在2013年的Sony Xperia Z Ultra(Android 4.4)上,结果应用程序需要六秒钟才能解压缩3M的压缩数据,并且更改xz的压缩级别并没有明显影响这6秒的启动时间。是的,在运行Android 10的2018年三星S9上只需要1秒钟,但是老旧的手机需要更多的压缩,因为它们可用空间较少,因此在旧设备上为应用程序添加不可接受的启动延迟似乎是自我打败的,特别是如果替代方案java.util.zip.Inflater几乎是瞬间完成的:
byte[] data = new byte[ /* compressed size here */];
context.getAssets().open("file.z").read(data);
java.util.zip.Inflater i=new java.util.zip.Inflater();
i.setInput(data);
byte[] decompressed=new byte[ /* decompressed size here */ ];
i.inflate(decompressed); i.end();
data = decompressed; /* allow earlier byte[] to be gc'd */

为了实现快速启动,您只需支付APK大小的20%,而比使用xz文件(我使用zopfli进行压缩,以获得比gzip -9略小的体积,尽管它仍然比xz -0大)。

Tukaani的代码目前似乎没有提供与setInput等效的功能。 Tukaani的XZDecDemo.java包含注释“由于XZInputStream在内部执行一些缓冲,因此不需要BufferedInputStream来提高性能”,但为了完整起见,我还是尝试了它:

byte[] data = new byte[ /* decompressed size here */ ];
new org.tukaani.xz.XZInputStream(
    new java.io.BufferedInputStream(
        context.getAssets().open("file.xz"),
        /* compressed size here */)).read(data);

然而,这对于6秒的延迟没有任何显著的影响(因此似乎评论是正确的:无论哪种方式,性能都很差)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接