LoginSignup
26
24

More than 5 years have passed since last update.

Unity C# Zip化したアセットバンドル(ファイル)を解凍

Last updated at Posted at 2015-03-30

●dotnetzipのページ ここからダウンロードする
http://dotnetzip.codeplex.com/

●上記ダウンロードの中にあるIonic.Zip.dllをUnityが認識するScriptsなどの適当なフォルダへおく

●下記ソースコードを呼ぶようにする。
 (今回はEditorからコールするようにしたけど本来は内部から呼ぶはず)

UnzipBundleFIle.cs
using UnityEngine;
using UnityEditor;
using System.Collections;
using Ionic.Zip;
using Ionic.Zlib;

public class UnzipBundleFIle
{
    [MenuItem("Assets/UnzipBundleFiles")]
    static void UnZipBundleFile()
    {
        // zipファイル読み込み
        using (ZipFile zip = new ZipFile("・・・・・・/myAssetBundle2.zip"))
        {
            // 出力先フォルダ名、たぶんUnity側が読めるフォルダじゃなきゃいけない
            string exportPath = "・・・・・/Assets";
            //ZIP書庫内のエントリを取得 
            foreach (Ionic.Zip.ZipEntry entry in zip)
            {
                //エントリを展開する 
                entry.Extract(exportPath);
            }
        }

        Debug.Log("UnZip OK");
    }
}

●上記実機で問題が出たので追記

 ------------------ 問題点と解決方法 ------------------
 ●iOSでクロスコンパイルエラーが出る。
  解決方法Ionic.Zip.dllでは無くIonic.Zip.CF.dllを使用する。

  Ionic.Zip.CF.dllhttp://dotnetzip.codeplex.com/からダウンロードしたフォルダ構成の
  zip-v1.9-CompactFrameworkReleaseにある。

 ●Androidでビルドすると下記①で落ちて②のエラーが出る
  ①using (ZipInputStream decompressStream = new ZipInputStream("zipファイルのMemoryStream"))
  ②Encoding name 'IBM437' not supported. Parameter name:name

  解決方法C:\Program Files\Unity501f1\Editor\Data\Mono\lib\mono\2.0にある
        I18N.West.dllを使用する。

   実行するUnityプロジェクトのAssetsフォルダの下に上記DLLを入れてビルドするとエラーにはならない。

  参考ページ
   http://forum.unity3d.com/threads/ionic-zip-dll-does-not-work-in-build.165841/
   
   http://stackoverflow.com/questions/10858690/get-encoding-fails-when-i-build-monodroid-project-with-unshared-runtime
   これを見る限りMonoのAndroidビルドにIBM437のエンコードが含まれていないみたい。

ソースも忘れないようにメモ

UnZipThread

using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Text.RegularExpressions;
using Ionic.Zip;

public class UnZipThread{

    public Action UnZipProgress;
    public Action UnZipEnd;
    public Action NextCallFunction;

    public AutoResetEvent ThreadEvent
    {
        get { return _threadEvent; }
    }


    private AutoResetEvent _threadEvent;
    public bool ThreadSleepFlg = true;


    //// 処理中INDEX
    //private int _listIndex;
    //public int ListIndex
    //{
    //    get { return _listIndex; }
    //    set { this._listIndex = value; }
    //}

    // 書込先ストリーム
    private MemoryStream _unZipMs = new MemoryStream();
    public MemoryStream UnZipMs
    {
        get { return _unZipMs; }
        set { this._unZipMs = value; }
    }


    // 保存先ファイルパス
    private string _savePath;
    public string SavePath
    {
        get { return _savePath; }
        set { this._savePath = value; }
    }


    // エラー文字列
    private string _errString = "";
    public string ErrString
    {
        get { return _errString; }
        set { this._errString = value; }
    }


    // 書込済み文字数
    private long _fileLength = 0;
    public long FileLength
    {
        get { return _fileLength; }
        set { this._fileLength = value; }
    }

    // チェック用ファイル名
    private string _fileName;
    public string FileName
    {
        get { return _fileName; }
        set { this._fileName = value; }
    }

    // UnZip進捗
    private float _unZipProgressValue;
    public float UnZipProgressValue
    {
        get { return _unZipProgressValue; }
        set { this._unZipProgressValue = value; }
    }


    private Thread ThreadEntity;


    /// <summary>
    /// Zip解凍スレッドスタート
    /// </summary>
    /// <returns></returns>
    public void ThreadDownLoadStart()
    {
        _errString = "ZipThreadStart";
        ThreadSleepFlg = false;
        Thread unzip = new Thread(new ThreadStart(FileUnZip));
        _threadEvent = new AutoResetEvent(true);
        unzip.Start();
    }

    /// <summary>
    /// Zip解凍用スレッド休止
    /// </summary>
    public void ThreadDownLoadPause()
    {
        _threadEvent.WaitOne();
        ThreadSleepFlg = true;
    }

    /// <summary>
    /// Zip解凍用スレッド再開
    /// </summary>
    public void ThreadDownLoadReStart()
    {
        _threadEvent.Set();
        ThreadSleepFlg = false;
    }

    /// <summary>
    /// Zip解凍用スレッドリセット
    /// </summary>
    public void ThreadDownLoadReset()
    {
        ThreadSleepFlg = true;
        _threadEvent.Reset();
        _threadEvent = null;

    }


    /// <summary>
    /// Unzipストリームセット処理
    /// </summary>
    /// <param name="addUrl"></param>
    private void UnZipDataStreamSet(MemoryStream unzipdata,DownLoadData setdownloaddata)
    {
        setdownloaddata.ZipFileData = new MemoryStream();
        lock (setdownloaddata.ZipFileData)
        {
            MemoryStream UnZipStream = new MemoryStream();
            UnZipStream = unzipdata;
            setdownloaddata.UnZipDataList.Add(UnZipStream);
        }
    }

    /// <summary>
    /// ファイルの解凍処理
    /// </summary>
    public void FileUnZip()
    {
        while (true)
        {
            int downloadcount = SingletonDownLoadData.Instance.DownLoadDataList.Where(download => download.UnZipEndFlg == false).Count();
            if (downloadcount > 0)
            {
                //_errString = "DownLoadCnt=" + downloadcount.ToString();
                // 最初にヒットしたものを取得
                DownLoadData setDownLoadData = SingletonDownLoadData.Instance.DownLoadDataList.Where(download => download.UnZipEndFlg == false).First();

                try
                {
                    _errString = "ZipCountOK";
                    // Zipファイルストリームの読み取り位置をゼロにセット
                    setDownLoadData.ZipFileData.Position = 0; ;
                    _errString = "ZipPos 0";

                    using (ZipInputStream decompressStream = new ZipInputStream(setDownLoadData.ZipFileData))
                    {
                        _errString = "ZipInputStream";
                        ZipEntry zipEntry = decompressStream.GetNextEntry();
                        while (zipEntry != null)
                        {
                            _errString = _errString + " ZipEntry";
                            // 書き込み領域を初期化
                            MemoryStream writeSpace = new MemoryStream();
                            writeSpace.Position = 0;
                            _errString = _errString + " UnZip Position = 0";
                            //展開するファイルを読み込む
                            byte[] buffer = new byte[2048];
                            int len;
                            while ((len = decompressStream.Read(buffer, 0, buffer.Length)) > 0)
                            {
                                //ファイルに書き込む
                                writeSpace.Write(buffer, 0, len);
                            }
                            _errString = _errString + " UnZip writeSpace";

                            // 書き込まれたストリームをデータクラスのファイル用のリストに追加
                            UnZipDataStreamSet(writeSpace, setDownLoadData);
                            setDownLoadData.FileNameList.Add(zipEntry.FileName);

                            _fileName = zipEntry.FileName;
                            UnZipProgress();
                            ////******************************************************************************


                            ////展開先のファイル名を決定
                            //string fileName = System.IO.Path.GetFileName(zipEntry.FileName);
                            ////展開先のフォルダを決定
                            //string destDir = System.IO.Path.Combine(@"C:\temp",
                            //    System.IO.Path.GetDirectoryName(zipEntry.FileName));
                            //System.IO.Directory.CreateDirectory(destDir);
                            ////展開先のファイルのフルパスを決定
                            //string destPath = System.IO.Path.Combine(destDir, fileName);

                            ////書き込み先のファイルを開く
                            //System.IO.FileStream writer = new System.IO.FileStream(
                            //    destPath, System.IO.FileMode.Create,
                            //    System.IO.FileAccess.Write);
                            ////ファイルに書き込む
                            //writer.Write(writeSpace.GetBuffer(), 0, (int)writeSpace.Length);
                            ////閉じる
                            //writer.Close();

                            ////******************************************************************************

                            // Zipファイル内のエントリーを次に進める
                            zipEntry = decompressStream.GetNextEntry();
                        }
                        setDownLoadData.UnZipEndFlg = true;
                    }
                    _errString = _errString + " UnZip OK";
                }
                catch (Exception ex)
                {
                    _errString = _errString + " Error=" + ex.Message;
                    // スレッドをスリープ状態へ
                    ThreadDownLoadPause();
                }
            }
            else
            {
                _errString = " ThreadSuspend";
                UnZipEnd();
                // 処理するものがなければスレッド一時停止
                // スレッドをスリープ状態へ
                ThreadDownLoadPause();
            }
        }
    }
}

26
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
24