Android 使用 7z 压缩字符串(工作总结)

写在前面

 通过阅读本篇文章,那你可以学(liao)习(jie)在android中如何对数据进行压缩(String->byte[]),
 对文件进行压缩和解压缩。阅读本篇文章大约需要五到十分钟,本人菜鸟,希望多多交流。

对数据进行压缩

  1. 到7z 官网下载 最新的 sdk 文件。 传送门: http://www.7-zip.org/sdk.html
    这里写图片描述

    1. 将我们需要的代码 cv 到我们项目中。路径:java/ servenZip

    这里写图片描述

    1. 讲代码复制到我们项目中后,自己手写压缩 方法。
public byte[] lzmaZip(String xml) throws IOException{   
  BufferedInputStream inStream = new BufferedInputStream(new ByteArrayInputStream(xml.getBytes()));   
  ByteArrayOutputStream bos = new ByteArrayOutputStream();   

  boolean eos = true;   
    Encoder encoder = new Encoder();   
    encoder.SetEndMarkerMode(eos);   
    encoder.WriteCoderProperties(bos);   
    long fileSize = xml.length();   
    if (eos)   
      fileSize = -1;   
    for (int i = 0; i < 8; i++)   
      bos.write((int)(fileSize >>> (8 * i)) & 0xFF);   
    encoder.Code(inStream, bos, -1, -1, null);   
    return bos.toByteArray() ;   
}   

*: Encoder 为 Compression / LZMA / Encoder .

  1. 对与 我们获得到的 byte [] ,我们肯定是持怀疑态度的。接下来我们就需要 通过 大神的项目 来验证我们的办法是否正确了。github:https://github.com/hzy3774/AndroidP7zip (不是本人),该大神通过c 代码,来实现 7z 解压缩。并且作者 很负责 很热心,我在这里 帮他打一个广告…. 手动笑脸 ☻。(大神的项目 c 使用的头文件 会使用到 ndk 版本位14以下的,所以 我最开始用 ndk16编译的时候 出现头文件丢失的情况。笔者运行时间:2017年12月4日 16:28:46)。

  2. 将我们获取的 byte [] 通过文件保存的方式保存到本地,并且后缀名 为7z.

try {
            byte[] ss = SevenZipUtil.lzmaZip("大吉大利,今晚吃鸡!随着最近几年健身热," +
                    "鸡胸肉好像已经成了网红。中国人到底有多爱吃鸡肉?中国从什么开始流行吃鸡?" +
                    "鸡肉又是怎么一步步登上餐桌的? ");
            createFileWithByte(ss);
            appUtils.logError("7z 压缩后:"+ Arrays.toString(ss));
        } catch (IOException e) {
            e.printStackTrace();
        }

byte [] 保存成文件

/**
     * 根据byte数组生成文件
     *
     * @param bytes
     *            生成文件用到的byte数组
     */
    private void createFileWithByte(byte[] bytes) {
        // TODO Auto-generated method stub
        /**
         * 创建File对象,其中包含文件所在的目录以及文件的命名
         */
        File file = new File(Environment.getExternalStorageDirectory()
                .getAbsolutePath() + File.separator + "ds",
                "two.7z");
        // 创建FileOutputStream对象
        FileOutputStream outputStream = null;
        // 创建BufferedOutputStream对象
        BufferedOutputStream bufferedOutputStream = null;
        try {
            // 如果文件存在则删除
            if (file.exists()) {
                file.delete();
            }
            // 在文件系统中根据路径创建一个新的空文件
            file.createNewFile();
            // 获取FileOutputStream对象
            outputStream = new FileOutputStream(file);
            // 获取BufferedOutputStream对象
            bufferedOutputStream = new BufferedOutputStream(outputStream);
            // 往文件所在的缓冲输出流中写byte数据
            bufferedOutputStream.write(bytes);
            // 刷出缓冲输出流,该步很关键,要是不执行flush()方法,那么文件的内容是空的。
            bufferedOutputStream.flush();
        } catch (Exception e) {
            // 打印异常信息
            e.printStackTrace();
        } finally {
            // 关闭创建的流对象
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bufferedOutputStream != null) {
                try {
                    bufferedOutputStream.close();
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
        }
    }

保存到手机上 成功之后 ,我们使用 大神的apk ,寻找到该文件夹所在位置,进行解压。然后我们进入文件管理界面,寻找解压后的文件,查看文件内容,经过 验证,该方法 可行。所以在这里 做下 笔记。 也来 填充一下 自己博文 较少的情况。(实力太菜…)

最后加上 本人使用的 工具类 SevenZipUtil:

/**
 * 解压 7z文件
 * Created by pul on 2017/12/1.
 */

public class SevenZipUtil {
    private final String TAG = "SevenZipUtil";

    /**
     * 将字符串 压缩 转换为 byte 数组
     *
     * @param xml
     * @return
     * @throws IOException
     */
    public static byte[] lzmaZip(String xml) throws IOException {
        BufferedInputStream inStream = new BufferedInputStream(new ByteArrayInputStream(xml.getBytes()));
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        boolean eos = true;
        Encoder encoder = new Encoder();
        encoder.SetEndMarkerMode(eos);
        encoder.WriteCoderProperties(bos);
        long fileSize = xml.length();
        if (eos)
            fileSize = -1;
        for (int i = 0; i < 8; i++)
            bos.write((int) (fileSize >>> (8 * i)) & 0xFF);
        encoder.Code(inStream, bos, -1, -1, null);
        return bos.toByteArray();
    }

    /**
     * 解压缩 7z文件
     */
    public void extractile(String filepath) {
        RandomAccessFile randomAccessFile = null;
        IInArchive inArchive = null;

        try {
            randomAccessFile = new RandomAccessFile(filepath, "r");
            inArchive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile));

            // Getting simple interface of the archive inArchive
            ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface();

            Log.e(TAG,"  Hash  |  Size  | Filename");
            Log.e(TAG,"----------+------------+---------");

            for (final ISimpleInArchiveItem item : simpleInArchive.getArchiveItems()) {
                final int[] hash = new int[]{0};
                if (!item.isFolder()) {
                    ExtractOperationResult result;

                    final long[] sizeArray = new long[1];
                    result = item.extractSlow(new ISequentialOutStream() {
                        public int write(byte[] data) throws SevenZipException {

                            //Write to file
                            FileOutputStream fos;
                            try {
                                File file = new File(item.getPath());
                                //error occours below
//                 file.getParentFile().mkdirs();
                                fos = new FileOutputStream(file);
                                fos.write(data);
                                fos.close();

                            } catch (FileNotFoundException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            } catch (IOException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }

                            hash[0] ^= Arrays.hashCode(data); // Consume data
                            sizeArray[0] += data.length;
                            return data.length; // Return amount of consumed data
                        }
                    });
                    if (result == ExtractOperationResult.OK) {
                        Log.e(TAG,String.format("%9X | %10s | %s", //
                                hash[0], sizeArray[0], item.getPath()));
                    } else {
                        Log.e(TAG,"Error extracting item: " + result);
                    }
                }
            }
        } catch (Exception e) {
            Log.e(TAG,"Error occurs: " + e);
            e.printStackTrace();
            System.exit(1);
        } finally {
            if (inArchive != null) {
                try {
                    inArchive.close();
                } catch (SevenZipException e) {
                    System.err.println("Error closing archive: " + e);
                }
            }
            if (randomAccessFile != null) {
                try {
                    randomAccessFile.close();
                } catch (IOException e) {
                    System.err.println("Error closing file: " + e);
                }
            }
        }
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值