Unity3d热更新(四):压缩文件

之前提到过通过AssetBundle.CreateFromFile读取本地AssetBundle,因为该方法只能读取未压缩的AssetBundle,所以打包AssetBundle时,需要选择BuildAssetBundleOptions.UncompressedAssetBundle未压缩模式,然后使用LZMA或GZIP压缩后上传服务器。本地下载后需要解压缩保存在Application.persistentDataPath目录下。

下面说明如何压缩AssetBundle。

首先需要下载7-zip的C#核心文件,下载地址http://www.7-zip.org/sdk.html

Unity3d热更新(四):压缩文件_第1张图片
解压后将CS文件夹下的7zip文件夹导入Unity工程,下面是一个Demo,可以直接用。
using UnityEngine;
using System.Collections;
using UnityEditor;
using SevenZip.Compression.LZMA;
using System.IO;
using System;

// 压缩或解压文件
public class CompressAndDecompress : Editor {

    // 压缩Unity3D文件
    [MenuItem("Compress/Compress Unity3D File")]
    static void CompressUnity3DFile()
    {
        string path = EditorUtility.OpenFilePanel("Compress file", "", "unity3d");
        CompressFile(path);
    }

    // 压缩Lua文件
    [MenuItem("Compress/Compress Lua File")]
    static void CompressLuaFile()
    {
        string path = EditorUtility.OpenFilePanel("Compress file", "", "lua");
        CompressFile(path);
    }

    // 压缩文件
    static void CompressFile(string path)
    {
        if (path.Length != 0)
        {
            int lastDotIndex = path.LastIndexOf(".");
            string outputPath = path.Substring(0, lastDotIndex + 1) + "zip";
            CompressFileLZMA(path, outputPath);
            AssetDatabase.Refresh();
            EditorUtility.DisplayDialog("压缩文件", "文件已压缩完成", "确认");
        }
    }

    // 解压Unity3D文件
    [MenuItem("Compress/Decompress Unity3D File")]
    static void DecompressUnity3DFile()
    {
        DecompressFile("unity3d");
    }

    // 解压Lua文件
    [MenuItem("Compress/Decompress Lua File")]
    static void DecompressLuaFile()
    {
        DecompressFile("lua");
    }

    static void DecompressFile(string extension)
    {
        string path = EditorUtility.OpenFilePanel("Decompress file", "", "zip");

        if (path.Length != 0)
        {
            int lastDotIndex = path.LastIndexOf(".");
            string outputPath = path.Substring(0, lastDotIndex + 1) + extension;
            DecompressFileLZMA(path, outputPath);
            AssetDatabase.Refresh();
            EditorUtility.DisplayDialog("解压文件", "文件已解压完成", "确认");
        }
    }

    // 压缩文件夹中的文件
    [MenuItem("Compress/Compress Files In Directory")]
    static void CompressFilesInDirectory()
    {
        string path = EditorUtility.OpenFolderPanel("Compress Files In Directory", "", "");

        if (path.Length != 0)
        {
            DirectoryInfo source = new DirectoryInfo(path);
            DirectoryInfo target = new DirectoryInfo(path + "_compress");

            if (target.Exists)
            {
                target.Delete(true);
            }

            target.Create();
            target.Refresh();

            // 复制源文件夹到目标文件夹
            CopyAll(source, target);
            ListFiles((FileSystemInfo)target, true);
            EditorUtility.DisplayDialog("压缩文件夹", "文件夹中所有的文件已压缩完成", "确认");
        }
    }

    // 解压文件夹中的文件
    //[MenuItem("Compress/Decompress Files In Directory")]
    static void DecompressFilesInDirectory()
    {
        string path = EditorUtility.OpenFolderPanel("Decompress Files In Directory", "", "");

        if (path.Length != 0)
        {
            DirectoryInfo source = new DirectoryInfo(path);
            DirectoryInfo target = new DirectoryInfo(path + "_decompress");

            if (target.Exists)
            {
                target.Delete(true);
            }

            target.Create();
            target.Refresh();

            // 复制源文件夹到目标文件夹
            CopyAll(source, target);
            ListFiles(target, false);
            EditorUtility.DisplayDialog("解压文件夹", "文件夹中所有的文件已解压完成", "确认");
        }
    }

    // 使用LZMA算法压缩文件
    private static void CompressFileLZMA(string inFile, string outFile)
    {
        Encoder coder = new Encoder();
        FileStream input = new FileStream(inFile, FileMode.Open);
        FileStream output = new FileStream(outFile, FileMode.Create);

        coder.WriteCoderProperties(output);

        byte[] data = BitConverter.GetBytes(input.Length);

        output.Write(data, 0, data.Length);

        coder.Code(input, output, input.Length, -1, null);
        output.Flush();
        output.Close();
        input.Close();
    }

    // 使用LZMA算法解压文件
    private static void DecompressFileLZMA(string inFile, string outFile)
    {
        Decoder coder = new Decoder();
        FileStream input = new FileStream(inFile, FileMode.Open);
        FileStream output = new FileStream(outFile, FileMode.Create);

        byte[] properties = new byte[5];
        input.Read(properties, 0, 5);

        byte[] fileLengthBytes = new byte[8];
        input.Read(fileLengthBytes, 0, 8);
        long fileLength = BitConverter.ToInt64(fileLengthBytes, 0);

        coder.SetDecoderProperties(properties);
        coder.Code(input, output, input.Length, fileLength, null);
        output.Flush();
        output.Close();
        input.Close();
    }

    // 复制源文件夹到目标文件夹
    public static void CopyAll(DirectoryInfo source, DirectoryInfo target, ArrayList extensions = null)
    {
        if (source.FullName.ToLower() == target.FullName.ToLower())
        {
            return;
        }

        // 检测目标文件是否存在,如果不存在,则创建
        if (!Directory.Exists(target.FullName))
        {
            Directory.CreateDirectory(target.FullName);
            target.Refresh();
        }

        // 复制文件至目标文件夹
        foreach (FileInfo fi in source.GetFiles())
        {
            if (extensions == null || extensions.Count == 0)
            {
                if (fi.Extension != ".meta")
                {
                    fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);
                }
            }
            else
            {
                if (extensions.Contains(fi.Extension))
                {
                    fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);
                }
            }
            
        }

        // 使用递归复制子文件夹
        foreach (DirectoryInfo sourceSubDir in source.GetDirectories())
        {
            DirectoryInfo targetSubDir = target.CreateSubdirectory(sourceSubDir.Name);
            CopyAll(sourceSubDir, targetSubDir, extensions);
        }
    }

    // 遍历文件夹中的所有文件,压缩或解压缩
    public static void ListFiles(FileSystemInfo info, bool isCompress)
    {
        if (!info.Exists)
        {
            return;
        }

        DirectoryInfo dir = info as DirectoryInfo;

        // 不是目录
        if (dir == null)
        {
            return;
        }

        FileSystemInfo[] files = dir.GetFileSystemInfos();

        for (int i = 0; i < files.Length; i++)
        {
            FileInfo file = files[i] as FileInfo;

            // 是文件
            if (file != null)
            {
                string fullName = file.FullName;

                // 如果是压缩文件
                if (isCompress)
                {
                    if (file.Extension == ".unity3d" || file.Extension == ".lua")
                    {
                        string outputPath = file.FullName.Replace(file.Extension, ".zip");
                        CompressFileLZMA(fullName, outputPath);
                        File.Delete(fullName);
                    }
                }
                // 如果是解压文件
                else
                {
                    if (file.Extension == ".zip")
                    {
                        string outputPath = file.FullName.Replace(file.Extension, ".unity3d");
                        DecompressFileLZMA(fullName, outputPath);
                        File.Delete(fullName);
                    }
                }

            }
            else
            {
                ListFiles(files[i], isCompress);
            }
        }
    }
}


你可能感兴趣的:(Unity)