1. 程式人生 > >unity-zip壓縮與解壓

unity-zip壓縮與解壓

  前一段時間在實現unity動態熱更新的時候,開始研究下了unity的zip壓縮與解壓縮的實現,這個過程中共發現三種壓縮與解壓縮的技術,分別是:

  1、LZMA壓縮與解壓縮(相關地址:http://www.xuanyusong.com/archives/3095)

這種壓縮技術在上面例子中實現的效果是將一個檔案轉化為.zip壓縮包,然後可以再轉化回來,所以這個暫時沒有找到辦法將一個資料夾壓縮,或是將已經用壓縮工具壓縮好的壓縮包進行解壓。

  2、Ionic.Zip.dll檔案的壓縮與解壓縮(相關地址:http://blog.csdn.net/jayzai/article/details/7563248)

這種技術實現壓縮與解壓縮比較簡單,但是就是檢視dll檔案的函式介面比較麻煩,而且也是暫時沒有找到將一個資料夾壓縮的方法。

  3、ICSharpCode.SharpZipLib.dll檔案的壓縮與解壓縮

這個為 最終在我的專案中選用的壓縮技術,實現並不複雜,只需要在unity中放入ICSharpCode.SharpZipLib.dll這個動態連結庫即可,一般動態連結庫放在專案目錄中\Assets\Plugins目錄下

基本程式碼

using UnityEngine;
using System.Collections;
using System;
using System.IO;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Zip;




public class SharpZip : MonoBehaviour
{
    private string downURL = "";
    //string sourcesPath = "";
    string targetPath = "";
    string filename = "test.zip";
    private WWW wwwDown=null;
    
    private string testString = "";
    // Use this for initialization  


    void Update()
    {


    }
    void Start()
    {
        //sourcesPath = Application.dataPath + "/Zip";
#if UNITY_ANDROID || UNITY_IPHONE
        targetPath = Application.persistentDataPath;
#else
       
#endif


#if UNITY_EDITOR
        //實驗
        targetPath = Application.dataPath + "/CompressZip";
#endif
       


        testString += "pathURL:" + Application.dataPath + "/CompressZip" + "\n";
    }


    void OnGUI()
    {
        //GUI.Label(new Rect(0, 60, Screen.width, Screen.height), testString);
    }


    public void DecompressFileTest()
    {
        StartCoroutine(UnzipWithPath(targetPath + "/" + "image.zip"));
    }
    public void DecompressOpenFileTest()
    {
        
        
        
        
    }
    private int totalCount;
    private int doneCount;
    private int indicatorStep = 1;
    public IEnumerator UnzipWithPath(string path)
    {
        Debug.Log("paht is:" + path);
        //這是根目錄的路徑  
        string dirPath = path.Substring(0, path.LastIndexOf('/'));
        Debug.Log("dirpath is:" + dirPath);
        //ZipEntry:檔案條目 就是該目錄下所有的檔案列表(也就是所有檔案的路徑)  
        ZipEntry zip = null;
        //輸入的所有的檔案流都是儲存在這裡面的  
        ZipInputStream zipInStream = null;
        //讀取檔案流到zipInputStream  
        zipInStream = new ZipInputStream(File.OpenRead(path));
        //迴圈讀取Zip目錄下的所有檔案  
        while ((zip = zipInStream.GetNextEntry()) != null)
        {
            Debug.Log("name is:" + zip.Name + " zipStream " + zipInStream);
            UnzipFile(zip, zipInStream, dirPath);
            doneCount++;
            if (doneCount % indicatorStep == 0)
            {
                yield return new WaitForEndOfFrame();
            }
        }
        try
        {
            zipInStream.Close();
        }
        catch (Exception ex)
        {
            Debug.Log("UnZip Error");
            throw ex;
        }


        Debug.Log("解壓完成:" + path);
        testString += "解壓完成:" + path + "\n";
    }
    static void UnzipFile(ZipEntry zip, ZipInputStream zipInStream, string dirPath)
    {
        try
        {
            //檔名不為空  
            if (!string.IsNullOrEmpty(zip.Name))
            {
                string filePath = dirPath;
                filePath += ("/" + zip.Name);


                //如果是一個新的檔案路徑 這裡需要建立這個檔案路徑  
                if (IsDirectory(filePath))
                {
                    Debug.Log("Create  file paht " + filePath);
                    if (!Directory.Exists(filePath))
                    {
                        Directory.CreateDirectory(filePath);
                    }
                }
                else
                {
                    FileStream fs = null;
                    //當前資料夾下有該檔案  刪掉  重新建立  
                    if (File.Exists(filePath))
                    {
                        File.Delete(filePath);
                    }
                    fs = File.Create(filePath);
                    int size = 2048;
                    byte[] data = new byte[2048];
                    //每次讀取2MB  直到把這個內容讀完  
                    while (true)
                    {
                        size = zipInStream.Read(data, 0, data.Length);
                        //小於0, 也就讀完了當前的流  
                        if (size > 0)
                        {
                            fs.Write(data, 0, size);
                        }
                        else
                        {
                            break;
                        }
                    }
                    fs.Close();
                }
            }
        }
        catch (Exception e)
        {
            throw new Exception();
        }
    }




    /// <summary>  
    /// 判斷是否是目錄檔案  
    /// </summary>  
    /// <param name="path"></param>  
    /// <returns></returns>  
    static bool IsDirectory(string path)
    {


        if (path[path.Length - 1] == '/')
        {
            return true;
        }
        return false;
    }
}


最後在這裡還是需要重申由於安卓不同路徑下的讀寫許可權的問題,所以在實驗assetbundle熱更新的時候,路徑地址Application.persistentDataPath,而本地實驗地址就隨便使用了。

最後依然是demo下載地址:http://download.csdn.net/detail/xunni_5241/9622038

本人文章純屬個人總結,且某些demo在專案採用前可能來自網際網路,最終實驗驗證後實際專案中採用,若發現來自貴方,諒解;若發現,紕漏錯誤妄指正。