1. 程式人生 > >Android 使用 7z 壓縮字串(工作總結)

Android 使用 7z 壓縮字串(工作總結)

寫在前面

 通過閱讀本篇文章,那你可以學(liao)習(jie)在android中如何對資料進行壓縮(String->byte[]),
 對檔案進行壓縮和解壓縮。閱讀本篇文章大約需要五到十分鐘,本人菜鳥,希望多多交流。

對資料進行壓縮

    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);
                }
            }
        }
    }
}