如何在android中使用XZ lib压缩/解压缩文件
Posted
技术标签:
【中文标题】如何在android中使用XZ lib压缩/解压缩文件【英文标题】:how to use XZ lib to compress/decompress file in android 【发布时间】:2018-01-17 12:39:00 【问题描述】:https://tukaani.org/xz/java.html这个站点提供了一个XZ库,用于压缩/解压缩文件,我想试一试,但我迷路了。
有人有这方面的经验吗?还是教程?谢谢。
【问题讨论】:
你可以在这里找到一个类似的教程,它使用 gz,你只需将 GzipCompressorInputStream 与 XZCompressorInputStream 交换。记得添加依赖,仅此而已:) ***.com/a/55736666/1083128 【参考方案1】:我最近使用了这个库,这是我的 github 链接 XZ compression algorithm 上的工作代码。你可以在你的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 and Inflater 的ZLIB 压缩库。这在 Android 平台上运行良好。
【讨论】:
它给了我内存不足的错误。无论如何要修复它? 如果我能看到会有所帮助的错误日志。 :)【参考方案2】:您可以使用来自 Android AOSP 的 XZ-Java 静态库或 'org.tukaani:xz:1.8'lib 以 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());
【讨论】:
【参考方案3】:我的 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.git
和cp -r xz-java/src/org
放入我的应用程序的src
目录(并确保在我的javac
命令行中提及所有.java
文件—我仍然使用老式命令行脚本来编译我的应用程序;我没有为 Android Studio 或 Gradle 设置它们)。
但是,生成的应用需要 6 秒在 2013 年 Sony Xperia Z Ultra(Android 4.4)上解压缩 3M 压缩数据,并更改 @ 的压缩级别987654328@ 对 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 大小比使用 xz
文件的 APK 大小增加 20% 的费用(我使用 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 秒的延迟没有明显影响(因此评论似乎是正确的:无论哪种方式,性能都一样糟糕)。
【讨论】:
以上是关于如何在android中使用XZ lib压缩/解压缩文件的主要内容,如果未能解决你的问题,请参考以下文章
如何即时从 hyper::Response 解压缩 XZ 数据?