(十九)7

编程入门 行业动态 更新时间:2024-10-08 18:41:38

(十九)7

(十九)7

版权声明:本文为博主原创文章,未经博主允许不得转载。
本文纯个人学习笔记,由于水平有限,难免有所出错,有发现的可以交流一下。

一、概述

1.7z

一种文件压缩格式,具有高压缩比率,进行数据压缩有多种压缩算法可以选择。与其它压缩格式相比,得到的压缩文档较小,即压缩率最高,节省磁盘空间。

2.7-Zip

对 7z 的压缩格式,我们可以使用 7-Zip,下载地址。

完全免费而且开源的压缩软件,相比其他软件有更高的压缩比但同时耗费的资源也相对更多。支持压缩/ 解压缩:7z, XZ, BZIP2, GZIP, TAR, ZIP, WIM。

3.数据

压缩率:

压缩文件尺寸:

压缩得分:

压缩时间:

整体来说,7-Zip 的性能相对较好。

二、7zip 的使用

1.压缩等级

0	不压缩
1	快速压缩
5	正常压缩
7	最大压缩
9	极限压缩

2.压缩命令

7z a   [输出文件] [待压缩文件/目录] -mx=9 

-t7z 	压缩文件的格式为7z(压缩zip则为-tzip)
-mx=9	设置压缩等级为极限压缩

3.解压命令

7z x [压缩文件]  -o[输出目录]

三、命令行使用 7z

1.下载源码

要在安卓中进行使用,我们需要先下载 7zip 的源码。下载地址。

也可以使用命令行进行下载:

wget  .02/p7zip_16.02_src_all.tar.bz2

下载下来的是一个压缩包,进行解压查看。

2.选取格式

Runtime.getRuntime().exec(“xxx”)

7z 的使用不需要对执行过程进行干预,也就是不需要在执行过程中操作数据,只在乎最后得到一个 7z 文件或者解压出 7z 文件。因此可以使用命令行来使用 7zip 压缩与解压。(同理对于视频文件的压缩、转换也可以使用ffmpeg 命令行,但是对于实时编码摄像头数据就必须编码完成)

首先,我们需要在安卓手机中拥有 7zip 的可执行文件,类似 window 中的 7zip.exe。

进入刚才下载压缩包下的目录, ./CPP/ANDROID/7zr

7z	 使用了插件,能进行更多的格式支持(能支持 tar、zip 等)
7za	 只是用7zip
7zr  只支持7z格式

我们只需要 7z 的格式,所以这边我们采用的是 7zr,这是最精简的。(如果要使用 7za 的话也是可以,编译步骤一样)

3.编译

我们进入 7zr 目录,查看目录结构。

里面有个 makefile 文件,这个是在 eclipse 创建安卓项目时候使用,我们打开 makefile 文件进行查看,里面就有编译步骤。

进到 jni 目录进行查看,是两个 .mk 文件。

查看 Application.mk 文件。里面就是指定对应的平台,默认只有 armeabi,我们可以在这里进行对对应平台的添加。

# The ARMv7 is significanly faster due to the use of the hardware FPU
APP_ABI := armeabi
# p7zip armeabi and armeabi-v7a run at the same speed (p7zip does not use FPU)
# APP_ABI := armeabi armeabi-v7a
#APP_PLATFORM := android-8

修改为:

# The ARMv7 is significanly faster due to the use of the hardware FPU
APP_ABI := armeabi-v7a x86
# p7zip armeabi and armeabi-v7a run at the same speed (p7zip does not use FPU)
# APP_ABI := armeabi armeabi-v7a
#APP_PLATFORM := android-8

在 jni 目录下按 makefile 文件中写的,运行 ndk-build 。

注: NDK 的版本要使用旧的版本,否者会报错。这边个人是使用 ndk 12 进行编译,下载地址。(ndk 15 太新,编译出错,ndk 10 编译过得去,在项目运行时候 cmake 报错)

编译成功后的目录:

4.使用

先把生成的可执行文件拷贝到 assets 目录下,打包进 apk。

运行 7zip 前,先把可执行文件拷贝到安卓系统中。

	/*** 把 7z 拷贝到手机* @param view*/public void load(View view) {File diskFilename = new File(getFilesDir(), "7zr");//不存在,则进行拷贝if (!diskFilename.exists()) {String assetFilename;//根据cpu 拷贝不同的可执行文件if (Build.CPU_ABI.startsWith("armeabi") ||Build.CPU_ABI.equals("x86")) {assetFilename = "libs/" + Build.CPU_ABI + "/7zr";} else {Toast.makeText(this, "加载错误,平台不符", Toast.LENGTH_SHORT).show();return;}AssetsFileUtil.copyFromAssets(this, assetFilename, diskFilename.getAbsolutePath());}//存在但不能执行if (!diskFilename.canExecute()) {//设置可执行并diskFilename.setExecutable(true);}Toast.makeText(this, "加载7zr 结果:"+ (diskFilename.exists() && diskFilename.canExecute()),Toast.LENGTH_SHORT).show();}

然后使用代码进行 7zip 压缩和解压命令的执行。具体 demo 见末尾。

**注:**这边是对 sdcard 目录下的 7-Zip 文件夹进行压缩,所以在运行前需保证改文件夹存在。

四、NDK 使用 7z

1.设置编译动态库

在上面的配置基础上,配置编译成动态库。

修改 Android.mk 文件末尾,去除配置 pie,使用默认的。设置编译内容为动态库。

Android.mk:

# Needed since ANDROID 5, these programs run on android-16 (Android 4.1+)
# pie 是给可执行程序使用的 flag
# LOCAL_CFLAGS += -fPIE
# LOCAL_LDFLAGS += -fPIE -pieinclude $(BUILD_SHARED_LIBRARY)
# BUILD_EXECUTABLE 可执行文件
# BUILD_SHARED_LIBRARY 动态库
# BUILD_STATIC_LIBRARY 静态库

2.编译

与编译成执行文件一样的操作步骤,进行编译,等待一会,即可在 libs 下面生产对应的动态库。

3.添加动态库

新建 cpp/libs 文件夹,然后把生成的动态库拷贝进来。

在 app 下的 build.gradle 中添加 so 包的引用路径。(如果把 so 放在默认 jniLibs 文件夹下则不需要进行添加,也是可以的。)

android {...sourceSets {main {jniLibs.srcDirs = ['src/main/cpp/libs']}}
}

4.配置 NDK 运行的平台

在 app 的 build.gradle 中进行添加以下配置:

android {compileSdkVersion 28defaultConfig {......externalNativeBuild {cmake {cppFlags ""abiFilters 'armeabi-v7a','x86'}}}
}

5.配置 CMakeLists

在 app 的 build.gradle 中添加 CMakeLists 路径。

android {......externalNativeBuild {cmake {path "CMakeLists.txt"}}
}

在 app 下创建 CMakeLists.txt 文件。

CMakeLists.txt:

cmake_minimum_required(VERSION 3.4.1)set(LIB_DIR ${CMAKE_SOURCE_DIR}/src/main/cpp/libs/${ANDROID_ABI})
add_library(lib7zr SHARED IMPORTED)
set_target_properties(lib7zr PROPERTIES IMPORTED_LOCATION ${LIB_DIR}/lib7zr.so)#根据Android.mk引入头文件
#设置头文件查找目录
include_directories(src/main/cpp/lib7zr/CPP/7zip/Archive
src/main/cpp/lib7zr/CPP/7zip/Archive/7z
src/main/cpp/lib7zr/CPP/7zip/Archive/BZip2
src/main/cpp/lib7zr/CPP/7zip/Archive/Common
src/main/cpp/lib7zr/CPP/7zip/Archive/GZip
src/main/cpp/lib7zr/CPP/7zip/Archive/Cab
src/main/cpp/lib7zr/CPP/7zip/Archive/Lzma
src/main/cpp/lib7zr/CPP/7zip/Archive/Tar
src/main/cpp/lib7zr/CPP/7zip/Archive/Zip
src/main/cpp/lib7zr/CPP/7zip/Archive/Split
src/main/cpp/lib7zr/CPP/7zip/Archive/Z
src/main/cpp/lib7zr/CPP/7zip/Compress
src/main/cpp/lib7zr/CPP/7zip/Crypto
src/main/cpp/lib7zr/CPP/7zip/UI/Console
src/main/cpp/lib7zr/CPP/7zip/UI/Common
src/main/cpp/lib7zr/CPP/Windows
src/main/cpp/lib7zr/CPP/Common
src/main/cpp/lib7zr/CPP/7zip/Common
src/main/cpp/lib7zr/C
src/main/cpp/lib7zr/CPP/myWindows
src/main/cpp/lib7zr/CPP
src/main/cpp/lib7zr/CPP/include_windows)add_library(native-libSHAREDsrc/main/cpp/native-lib.cpp)target_link_libraries(native-liblib7zrlog )

这个 CMakeLists.txt 编写是模仿 7zip 进行编写的。查看 Android.mk,把引用到的头文件拷贝进来就是了。

上面的 CMakeLists.txt 使用到了一些 7zip 的文件,我们需要把这些文件拷贝到 app/src/main/cpp/lib7zr 下。

7zip 下文件:

拷贝后文件:

6.编写 C 代码

在 app/src/main/cpp 下创建 native-lib.cpp 文件,进行 C 代码的编写。

native-lib:

#include <jni.h>
#include <string>
#include <7zTypes.h>
//
#include <android/log.h>#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "7zr",__VA_ARGS__);//c++与c兼容
// int a(int x) i_ai
// i_a
//表示这个函数在别的地方实现
extern int MY_CDECL main(
#ifndef _WIN32int numArgs, char *args[]
#endif
);void strArgs(const char *cmd, int &args, char pString[66][1024]);extern "C"
JNIEXPORT jint JNICALL
Java_com_xiaoyue_project7zip_ZipCode_exec(JNIEnv *env, jclass type, jstring cmd_) {const char *cmd = env->GetStringUTFChars(cmd_, 0);//7zr a /sdcard/7-Zip.7z /sdcard/7-Zip -mx=9int numArgs;char temp[66][1024] = {0};//分割字符串 将值填入变量strArgs(cmd, numArgs, temp);char *args[] = {0};for (int i = 0; i < numArgs; ++i) {args[i] = temp[i];LOGE("%s", args[i]);}env->ReleaseStringUTFChars(cmd_, cmd);return main(numArgs,args);
}void strArgs(const char *cmd, int &numArgs, char argv[66][1024]) {//获得字符串长度int size = strlen(cmd);//argv的两个下标int a = 0, b = 0;//0 = false//记录是否进入空格//7zr a /sdcard/7-Zip.7z /sdcard/7-Zip -mx=9//7zr\0int inspace = 0;for (int i = 0; i < size; ++i) {char c = cmd[i];switch (c) {case ' ':case '\t':if (inspace) {//字符串结束符号argv[a][b++] = '\0';a++;//加入下一个有效字符前 复原b = 0;inspace = 0;}break;default://如果是字符inspace = 1;argv[a][b++] = c;break;}}//7zr a /sdcard/7-Zip.7z /sdcard/7-Zip -mx=9//如果最末尾不是空格 就不会进入  case ' ': case '\t': 补上最后一个结束符//if(inspace){}if (cmd[size - 1] != ' ' && cmd[size - 1] != '\t') {argv[a][b] = '\0';a++;}numArgs = a;
}

同时编写一个 java 类 ZipCode 进行加载 native-lib。

ZipCode:

public class ZipCode {static {System.loadLibrary("native-lib");}//7zr a xxx.7z xxpublic native static int exec(String cmd);
}

7.测试

在 MainActivity 中进行代码的调用。

	@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);File src = new File(Environment.getExternalStorageDirectory(), "7-Zip");File out = new File(Environment.getExternalStorageDirectory(), "7-Zip.7z");File out2 = new File(Environment.getExternalStorageDirectory(), "7-Zip_code");ZipCode.exec("7zr a " + out.getAbsolutePath() + " " + src.getAbsolutePath() + " -mx=9");ZipCode.exec("7zr x " + out.getAbsolutePath() + " -o" + out2.getAbsolutePath());}

注: 这边是对sdcard 目录下的 7-Zip 文件夹进行压缩,所以在运行前需保证改文件夹存在。

8.运行结果

在 sdcard 目录下生成 7-Zip.7z 压缩包和 7-Zip_code 解压文件夹。

五、使用场景

可以使用 7-Zip 对上传服务的文件进行压缩,减小体积。也可以使用 7-Zip 对 dex 文件进行压缩,减小 apk 的体积。

六、附

代码链接

更多推荐

(十九)7

本文发布于:2024-02-28 05:54:20,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1768460.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!