**(上)**
1,
(1)7Z是什么:
一种文件压缩格式,具有高压缩比率,进行数据压缩有多种压缩算法可以选择。与其它压缩格式相比,得到的压缩文档较小,即压缩率最高
(2)7-Zip:
完全免费而且开源的压缩软件,相比其他软件有更高的压缩比但同时耗费的资源也相对更多。支持压缩/ 解压缩:7z, XZ, BZIP2, GZIP, TAR, ZIP,WIM
(3)7z的好处:
节省磁盘的空间,节省上传下载的流量
(4)常见的压缩格式:
zip:一种规范开放的压缩文件,压缩算法主要使用 (原名DEFLATE /真空)
rar:RAR有专利保护,特别是编码也就是压缩程序是私有的。
tar:tar是Linux常见的一种归档文件格式(原生不包括压缩功能,压缩率最 差),tar一般和其他没有文件管理的压缩算法文件结合使用,用tar打包整个文件 目录结构成一个文件,再用gzip,bzip等压缩 。是Linux常见的压缩归档的处理 方法。
(5)7z:算法主要用lzma,7z的文件和管理程序都是开源的。
(6)压缩比较
文件压缩得分 文件压缩时间x压缩率(得分越低越牛)
(7)7zip的使用(在windows环境下)
1)下载地址:http://www.7-zip.org/
2)下载安装后的7-zip
3)源码下载地址https://sourceforge.net/projects/p7zip/files/
4)压缩等级
不压缩0(就是拷贝文件)
快速压缩1
正常压缩5(默认值)
最大压缩7
极限压缩9
5)压缩命令
7z a [输出文件] [待压缩文件/目录] -mx=9
9是压缩等级
cmd 进入当前目录
输入如下命令
7z a ../gang -mx=0
这个命令是把当前所有文件都压缩到…/gang的目录,压缩等级是0
6)解压命令
7z x [压缩文件] -o[输出目录]
注意-O与输出目录之间没有空格
我们把第六小点压缩的文件在解压回来
7z x ../gang.7z -o../gang
(8)7zip的使用(在android环境下)
1)源码下载地址:
https://sourceforge.net/projects/p7zip/files/
2)命令行中使用
Runtime.getRuntime().exec(“xxx”)
7z的使用不需要对执行过程进行干预,也就是不需要在执行过程中操作数据,只在乎最后得到一个7z文件或者解压出7z文件。因此可以使用命令行来使用7zip压缩与解压。(同理对于视频文件的压缩、转换也可以使用ffmpeg命令行,但是对于实时编码摄像头数据就必须编码完成)
具体需要四个步骤,我们看下哪四个步骤
第一步:
我们看下目录
-进入 目录/CPP/ANDROID/7zr
android目录中有三个文件夹,7z,7za,7zr
7z:使用了插件,能进行更多的格式支持(能支持tar、zip等)
7za:只是用7zip
7zr:只支持7z格式
我们这里只用7zr,我们来到7zr目录。目录下有两个文件
jni文件夹和makefile文件
我们看下makefile文件
TARGET=7zr
include ../makefile.inc
test: install
adb shell $(DEVICE_DIR)/7zr b
test_crc: install
adb shell $(DEVICE_DIR)/7zr -mm=crc b
test_complex: install
adb shell $(DEVICE_DIR)/7zr "-mm=*" b
test2:
adb push ./libs/armeabi-v7a/7zr $(DEVICE_DIR)/7zr-v7a
adb shell chmod 777 $(DEVICE_DIR)/7zr-v7a
adb shell $(DEVICE_DIR)/7zr-v7a b
test_all: install
adb push ../../../check/test/7zr433_7zip_lzma.7z $(DEVICE_DIR)
adb shell $(DEVICE_DIR)/7zr t $(DEVICE_DIR)/7zr433_7zip_lzma.7z
bench: install test
# FIXME这里是操作步骤
debug:
cd jni ; ndk-build NDK_DEBUG=1
adb push ./libs/armeabi/7zr /data/app/
adb push ./libs/armeabi/gdbserver /data/app/
adb shell chmod 777 /data/app/7zr
adb shell chmod 777 /data/app/gdbserver
adb forward tcp:1234: tcp:1234
adb shell /data/app/gdbserver :1234 /data/app/7zr
第二步:
默认编译出armeabi架构,可以根据自己的需要在CPP/ANDROID/7zr/jni/Application.mk中增加/修改,如编译armeabi-v7a和x86:
操作如下
APP_ABI := x86
改为:
APP_ABI := armeabi-v7a x86
这是Application.mk文件
# The ARMv7 is significanly faster due to the use of the hardware FPU
APP_ABI := armeabi-v7a
# p7zip armeabi and armeabi-v7a run at the same speed (p7zip does not use FPU)
# APP_ABI := armeabi armeabi-v7a
#APP_PLATFORM := android-8
CPP/ANDROID/7zr/jni目录下有两个文件,除了Application.mk外,还有一个Android.mk.我们看下它的部分代码
# Needed since ANDROID 5, these programs run on android-16 (Android 4.1+)
#与位置无关的可执行程序
LOCAL_CFLAGS += -fPIE
LOCAL_LDFLAGS += -fPIE -pie
#编译可执行文件
include $(BUILD_EXECUTABLE)
#编译动态库
#include $(BUILD_SHARED_LIBRARY)
#编译静态库
#include $(BUILD_STATIC_LIBRARY)
第三部 执行编译:jni在我的计算机上的目录是……\p7zip_16.02_src_all\p7zip_16.02\CPP\ANDROID\7zr\jni
cd jni
ndk-build
运行完之后会生成一个obj文件夹和一个libs文件件
cd obj
cd libs
你会发现有一个armeabi-v7a的文件夹和一个x86文件夹,就是我们刚才用ndk-build编译生成的。
得到一个可执行文件7zr
第三部拷贝到android 工程
我们新建一个NDK工程,把libs文件夹拷贝到android assets目录,如下图所示
看下我们的布局文件,很简单,就三个按钮
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.dn.lsn_12_demo.MainActivity">
<Button
android:onClick="load"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="加载可执行文件" />
<Button
android:onClick="pack"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="打包7z文件" />
<Button
android:onClick="unpack"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="解包7z文件" />
</LinearLayout>
点击加载可执行文件,然后执行打包7z文件,然后执行解包7z文件
工具类
package com.dn.lsn_12_demo.command;
import android.content.Context;
import android.os.Build;
import android.util.Log;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
/**
* @author Damon
* @date 2019/05/27
*/
public class CommandUtils {
/**
* 拷贝文件
*
* @param context
* @param binary
* @return
*/
public static boolean copyAssets2File(Context context, String binary) {
// /data/data/package
File filesDirectory = context.getFilesDir();
boolean ret = false;
InputStream is = null;
FileOutputStream fos = null;
try {
//根据cpu 拷贝不同的可执行文件
Log.e("Build.CPU_ABI: ",Build.CPU_ABI);
List<String> abiNames = Arrays.asList(context.getAssets().list("libs"));
if(!abiNames.contains(Build.CPU_ABI)){
return false;
}
is = context.getAssets().open("libs/" + Build.CPU_ABI + "/" + binary);
fos = new FileOutputStream(new File(filesDirectory,
binary));
byte[] buffer = new byte[2048];
int n;
while ((n = is.read(buffer)) != -1) {
fos.write(buffer, 0, n);
}
fos.flush();
ret = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != fos) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return ret;
}
public static String inputStream2String(InputStream inputStream) {
try {
BufferedReader r = new BufferedReader(new InputStreamReader(inputStream));
String str;
StringBuilder sb = new StringBuilder();
while ((str = r.readLine()) != null) {
sb.append(str);
}
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
package com.dn.lsn_12_demo;
import android.content.Context;
import android.os.AsyncTask;
import com.dn.lsn_12_demo.command.CommandUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* @author Damon
* @date 2019/05/27
*/
public class ZipHelper {
/**
* 执行结果回调
*/
public interface OnResultListener {
void onSuccess(String msg);
void onFailure(int errorno, String msg);
void onProgress(String msg);
}
/**
* 将可执行文件 从assets拷贝到 /data/data/包名 下
*
* @param context
* @param binaryName
* @return
*/
public static boolean loadBinary(Context context, String binaryName) {
// 把assets目录下的可执行文件拷贝到/data/data/包名
File binaryFile = new File(context.getFilesDir(), binaryName);
if (binaryFile.exists()) {
//存在 但不能执行
if (!binaryFile.canExecute()) {
//设置可执行并 返回加过
binaryFile.setExecutable(true);
}
} else {
//根据cpu abi拷贝可执行文件
if (CommandUtils.copyAssets2File(context, binaryName)) {
if (!binaryFile.canExecute()) {
//设置可执行并 返回加过
binaryFile.setExecutable(true);
}
}
}
return binaryFile.exists() && binaryFile.canExecute();
}
public static void execute(Context context, String cmd, OnResultListener listener) {
File filesDir = context.getFilesDir();
// /data/data/包名/7zr
new ExecuteAysnTask(filesDir.getAbsolutePath() + "/" + cmd, listener).execute();
}
/**
* 结果记录
*/
static class Result {
boolean success;
String output;
int errorno;
public Result(boolean success, String output, int errorno) {
this.success = success;
this.output = output;
this.errorno = errorno;
}
}
static class ExecuteAysnTask extends AsyncTask<Void, String, Result> {
private OnResultListener listener;
private String cmd;
public ExecuteAysnTask(String cmd, OnResultListener listener) {
this.cmd = cmd;
this.listener = listener;
}
@Override
protected Result doInBackground(Void... voids) {
Process process = null;
//执行结果输出
String out;
try {
//执行任务
process = Runtime.getRuntime().exec(cmd);
//查看是否执行完成
while (!isComplete(process)) {
//读取运行过程中的输出信息
BufferedReader reader = new BufferedReader(new InputStreamReader
(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
//报告执行过程
publishProgress(line);
}
}
int exitValue = process.exitValue();
//成功
if (exitValue == 0) {
out = CommandUtils.inputStream2String(process.getInputStream());
} else {
out = CommandUtils.inputStream2String(process.getErrorStream());
}
return new Result(exitValue == 0, out, exitValue);
} catch (IOException e) {
e.printStackTrace();
out = e.getMessage();
} finally {
if (null != process) {
process.destroy();
}
}
return new Result(false, out, -1);
}
@Override
protected void onProgressUpdate(String... values) {
listener.onProgress(values[0]);
}
@Override
protected void onPostExecute(Result result) {
if (result.success) {
listener.onSuccess(result.output);
} else {
listener.onFailure(result.errorno, result.output);
}
}
/**
* 查看程序是否结束
*
* @param process
* @return
*/
private boolean isComplete(Process process) {
try {
//如果已经结束则返回结果 否则会出现IllegalThreadStateException异常
process.exitValue();
return true;
} catch (IllegalThreadStateException e) {
}
return false;
}
}
}
Actitivity中调用
package com.dn.lsn_12_demo;
import android.Manifest;
import android.content.pm.PackageManager;
import android.nfc.Tag;
import android.os.Build;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.dn.lsn_12_demo.R;
import java.io.File;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//动态申请权限,因为等下我们解压压缩需要用到sd卡
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
String[] perms = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (checkSelfPermission(perms[0]) == PackageManager.PERMISSION_DENIED) {
requestPermissions(perms, 200);
}
}
File src = new File(Environment.getExternalStorageDirectory(), "7-Zip");
File out = new File(Environment.getExternalStorageDirectory(), "7-Zip.7z");
int result = ZipCode.exec("7zr a " + out.getAbsolutePath() + " "
+ src.getAbsolutePath() + " -mx=9");
Log.e(TAG, "ZipCode.exec: "+result);
}
/**
* 将assets下的可执行文件拷贝到应用私有目录
*
* @param view
*/
public void load(View view) {
boolean result = ZipHelper.loadBinary(this, "7zr");
Toast.makeText(this, "加载7zr结果:" + result, Toast.LENGTH_SHORT).show();
}
/**
* 压缩
* 7zr a [输出文件] [待压缩文件/目录] -mx=9
* 7zr a /sdcard/7-Zip.7z /sdcard/7-Zip -mx=9
*
* @param view
*/
public void pack(View view) {
//待压缩的文件
//9表示压缩等级
File src = new File(Environment.getExternalStorageDirectory(), "7-Zip");
File out = new File(Environment.getExternalStorageDirectory(), "7-Zip.7z");
ZipHelper.execute(this, "7zr a " + out.getAbsolutePath() + " "
+ src.getAbsolutePath() + " -mx=9", new ZipHelper.OnResultListener() {
@Override
public void onSuccess(String msg) {
Log.e(TAG, "执行成功");
}
@Override
public void onFailure(int errorno, String msg) {
Log.e(TAG, "执行失败");
Log.e(TAG, "错误码:"+errorno);
Log.e(TAG, "错误信息:"+msg);
}
@Override
public void onProgress(String msg)
{
//输出编译过程中的日志
Log.e(TAG, "正在执行:" + msg);
}
});
}
/**
* 解压
* 7zr x [压缩文件] -o[输出目录]
*
* @param view
*/
public void unpack(View view) {
File src = new File(Environment.getExternalStorageDirectory(), "7-Zip.7z");
File out = new File(Environment.getExternalStorageDirectory(), "7-Zip-unpack");
ZipHelper.execute(this, "7zr x " + src.getAbsolutePath() + " -o"
+ out.getAbsolutePath(), new ZipHelper.OnResultListener() {
@Override
public void onSuccess(String msg) {
Log.e(TAG, "执行成功");
}
@Override
public void onFailure(int errorno, String msg) {
Log.e(TAG, "执行失败");
Log.e(TAG, "错误码:"+errorno);
Log.e(TAG, "错误信息:"+msg);
}
@Override
public void onProgress(String msg) {
//输出编译过程中的日志
Log.e(TAG, "正在执行:" + msg);
}
});
}
}
看下运行结果
介绍一个小技巧,android studio中如何查看sdcard目录
(下)