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在專案採用前可能來自網際網路,最終實驗驗證後實際專案中採用,若發現來自貴方,諒解;若發現,紕漏錯誤妄指正。