Unity 工具 之 (SharpZipLib) 实现文件Zip的压缩和解压((可代密码)可一次压缩多个文件/文件夹)

这篇博客介绍了如何在Unity中使用SharpZipLib库进行文件和文件夹的压缩与解压操作,包括设置密码、压缩多个文件及文件夹,并提供了详细的步骤和关键代码示例。此外,还提到了获取和安装SharpZipLib库的不同方法,如通过GitHub或NuGet。
摘要由CSDN通过智能技术生成

 

 

Unity 工具 之 (SharpZipLib) 实现文件Zip的压缩和解压((可代密码)可一次压缩多个文件/文件夹)

 

目录

Unity 工具 之 (SharpZipLib) 实现文件Zip的压缩和解压((可代密码)可一次压缩多个文件/文件夹)

一、简单介绍

二、功能简介

三、效果预览

四、SharpZipLib 库查看或获取

五、实现步骤

六、关键代码


 

一、简单介绍

Unity 工具类,自己整理的一些游戏开发可能用到的模块,单独独立使用,方便游戏开发。

Unity 进行文件的压缩和解压,这里介绍使用 SharpZipLib 库进行压缩和解压,方便游戏数据的打包下载,更新一些资源等等,方法不唯一,感谢提供参考学习的朋友们,大牛们哈(借用下你们优秀代码,学习)。

 

二、功能简介

1、可压缩单个文件,可压缩单个文件夹

2、可压缩多个文件,可压缩多个文件夹

3、可混合压缩多个文件,和多个文件夹

4、可以文件路径解压文件、也可以 byte 流 解压文件

 

三、效果预览

 

四、SharpZipLib 库查看或获取

1、SharpZipLib库下载地址

使用SharpZipLib库,下载地址为:http://icsharpcode.github.io/SharpZipLib/ (这个之前网址好似进不去了)

可以尝试这个网址:https://github.com/icsharpcode/SharpZipLib

 

2、github 库如下

https://github.com/icsharpcode/SharpZipLib

 

3、可以点击旁边的 Release 查看最新的发布版本

 

4、Release 信息如下

网址:https://github.com/icsharpcode/SharpZipLib/releases

 

5、当然,还可以在 VS 的 NuGet 中查看或者获取

 

6、 NuGet 中 中搜索 SharpZipLib,便可安装到工程中

(有时候或有多个版本,根据需要选择即可)

 

五、实现步骤

1、打开Unity,新建空工程

 

2、添加脚本,实现文件的压缩解压功能逻辑,以及用于测试的脚本

 

3、在 VS 的 NuGet 中安装 SharpZipLib 库

 

4、如下安装成功

 

5、但是,回到Unity中,可能还是有报错

(应该有其他方法可以解决,知道的朋友还请留言告知一下哈,谢谢)

 

6、其实,VS 安装到了Unity 工程的 packages 文件夹下

 

7、可以查看到对应net版本的 SharpZipLib dll 文件

 

7、根据 Unity 使用的net版本,对应添加 dll到工程中,报错就会没有了

 

8、在工程中添加一些测试压缩的文件和文件夹

 

9、把测试脚本添加到场景中

 

10、运行场景,效果如上

(如果没有显示文件,工程文件中右键刷新一下就好了)

 

六、关键代码

1、Test_ZipWrapper

using ICSharpCode.SharpZipLib.Zip;
using UnityEngine;

public class Test_ZipWrapper : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Test_Zip();

        Test_UnZip();
    }

    #region Test_Zip

    
    void Test_Zip() {

        string[] zipFilePaths = new string[] {
            Application.dataPath+"/SharpZipLibWrapper/Test_Folder/Folder",
            Application.dataPath+"/SharpZipLibWrapper/Test_Folder/TestFile.txt",
        };

        string zipOutputPath = Application.dataPath + "/zipTest.zip";

        ZipWrapper.Zip(zipFilePaths, zipOutputPath, "password", new ZipCallback());
    }

   

    public class ZipCallback : ZipWrapper.ZipCallback {
        public override bool OnPreZip(ZipEntry _entry)
        {
            Debug.Log("OnPreZip Name: " + _entry.Name);
            Debug.Log("OnPreZip IsFile:" + _entry.IsFile);
            return base.OnPreZip(_entry);
        }

        public override void OnPostZip(ZipEntry _entry)
        {
            Debug.Log("OnPostZip Name: " + _entry.Name);
        }

        public override void OnFinished(bool _result)
        {
            Debug.Log("OnZipFinished _result: " + _result);
        }

    }

    #endregion

    #region Test_UnZip

    void Test_UnZip()
    {

        string zipFilePath = Application.dataPath + "/zipTest.zip";
        string zipOutputPath = Application.dataPath + "/UnZip";

        ZipWrapper.UnzipFile(zipFilePath, zipOutputPath, "password", new UnzipCallback());
    }

    public class UnzipCallback : ZipWrapper.UnzipCallback {
        public override bool OnPreUnzip(ZipEntry _entry)
        {
            Debug.Log("OnPreUnzip Name: " + _entry.Name);
            Debug.Log("OnPreUnzip IsFile:" + _entry.IsFile);
            return base.OnPreUnzip(_entry);
        }

        public override void OnPostUnzip(ZipEntry _entry)
        {
            Debug.Log("OnPostUnzip Name: " + _entry.Name);
            base.OnPostUnzip(_entry);
        }

        public override void OnFinished(bool _result)
        {
            Debug.Log("OnUnZipFinished _result: " + _result);
            base.OnFinished(_result);
        }
    }

    #endregion
}

 

2、ZipWrapper

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

public class ZipWrapper : MonoBehaviour
{
    #region ZipCallback
    public abstract class ZipCallback
    {
        /// <summary>
        /// 压缩单个文件或文件夹前执行的回调
        /// </summary>
        /// <param name="_entry"></param>
        /// <returns>如果返回true,则压缩文件或文件夹,反之则不压缩文件或文件夹</returns>
        public virtual bool OnPreZip(ZipEntry _entry)
        {
            return true;
        }

        /// <summary>
        /// 压缩单个文件或文件夹后执行的回调
        /// </summary>
        /// <param name="_entry"></param>
        public virtual void OnPostZip(ZipEntry _entry) { }

        /// <summary>
        /// 压缩执行完毕后的回调
        /// </summary>
        /// <param name="_result">true表示压缩成功,false表示压缩失败</param>
        public virtual void OnFinished(bool _result) { }
    }
    #endregion

    #region UnzipCallback
    public abstract class UnzipCallback
    {
        /// <summary>
        /// 解压单个文件或文件夹前执行的回调
        /// </summary>
        /// <param name="_entry"></param>
        /// <returns>如果返回true,则压缩文件或文件夹,反之则不压缩文件或文件夹</returns>
        public virtual bool OnPreUnzip(ZipEntry _entry)
        {
            return true;
        }

        /// <summary>
        /// 解压单个文件或文件夹后执行的回调
        /// </summary>
        /// <param name="_entry"></param>
        public virtual void OnPostUnzip(ZipEntry _entry) { }

        /// <summary>
        /// 解压执行完毕后的回调
        /// </summary>
        /// <param name="_result">true表示解压成功,false表示解压失败</param>
        public virtual void OnFinished(bool _result) { }
    }
    #endregion

    /// <summary>
    /// 压缩文件和文件夹
    /// </summary>
    /// <param name="_fileOrDirectoryArray">文件夹路径和文件名</param>
    /// <param name="_outputPathName">压缩后的输出路径文件名</param>
    /// <param name="_password">压缩密码</param>
    /// <param name="_zipCallback">ZipCallback对象,负责回调</param>
    /// <returns></returns>
    public static bool Zip(string[] _fileOrDirectoryArray, string _outputPathName, string _password = null, ZipCallback _zipCallback = null)
    {
        if ((null == _fileOrDirectoryArray) || string.IsNullOrEmpty(_outputPathName))
        {
            if (null != _zipCallback)
                _zipCallback.OnFinished(false);

            return false;
        }

        ZipOutputStream zipOutputStream = new ZipOutputStream(File.Create(_outputPathName));
        zipOutputStream.SetLevel(6);    // 压缩质量和压缩速度的平衡点
        if (!string.IsNullOrEmpty(_password))
            zipOutputStream.Password = _password;

        for (int index = 0; index < _fileOrDirectoryArray.Length; ++index)
        {
            bool result = false;
            string fileOrDirectory = _fileOrDirectoryArray[index];
            if (Directory.Exists(fileOrDirectory))
                result = ZipDirectory(fileOrDirectory, string.Empty, zipOutputStream, _zipCallback);
            else if (File.Exists(fileOrDirectory))
                result = ZipFile(fileOrDirectory, string.Empty, zipOutputStream, _zipCallback);

            if (!result)
            {
                if (null != _zipCallback)
                    _zipCallback.OnFinished(false);

                return false;
            }
        }

        zipOutputStream.Finish();
        zipOutputStream.Close();

        if (null != _zipCallback)
            _zipCallback.OnFinished(true);

        return true;
    }

    /// <summary>
    /// 解压Zip包
    /// </summary>
    /// <param name="_filePathName">Zip包的文件路径名</param>
    /// <param name="_outputPath">解压输出路径</param>
    /// <param name="_password">解压密码</param>
    /// <param name="_unzipCallback">UnzipCallback对象,负责回调</param>
    /// <returns></returns>
    public static bool UnzipFile(string _filePathName, string _outputPath, string _password = null, UnzipCallback _unzipCallback = null)
    {
        if (string.IsNullOrEmpty(_filePathName) || string.IsNullOrEmpty(_outputPath))
        {
            if (null != _unzipCallback)
                _unzipCallback.OnFinished(false);

            return false;
        }

        try
        {
            return UnzipFile(File.OpenRead(_filePathName), _outputPath, _password, _unzipCallback);
        }
        catch (System.Exception _e)
        {
            Debug.LogError("[ZipUtility.UnzipFile]: " + _e.ToString());

            if (null != _unzipCallback)
                _unzipCallback.OnFinished(false);

            return false;
        }
    }

    /// <summary>
    /// 解压Zip包
    /// </summary>
    /// <param name="_fileBytes">Zip包字节数组</param>
    /// <param name="_outputPath">解压输出路径</param>
    /// <param name="_password">解压密码</param>
    /// <param name="_unzipCallback">UnzipCallback对象,负责回调</param>
    /// <returns></returns>
    public static bool UnzipFile(byte[] _fileBytes, string _outputPath, string _password = null, UnzipCallback _unzipCallback = null)
    {
        if ((null == _fileBytes) || string.IsNullOrEmpty(_outputPath))
        {
            if (null != _unzipCallback)
                _unzipCallback.OnFinished(false);

            return false;
        }

        bool result = UnzipFile(new MemoryStream(_fileBytes), _outputPath, _password, _unzipCallback);
        if (!result)
        {
            if (null != _unzipCallback)
                _unzipCallback.OnFinished(false);
        }

        return result;
    }

    /// <summary>
    /// 解压Zip包
    /// </summary>
    /// <param name="_inputStream">Zip包输入流</param>
    /// <param name="_outputPath">解压输出路径</param>
    /// <param name="_password">解压密码</param>
    /// <param name="_unzipCallback">UnzipCallback对象,负责回调</param>
    /// <returns></returns>
    public static bool UnzipFile(Stream _inputStream, string _outputPath, string _password = null, UnzipCallback _unzipCallback = null)
    {
        if ((null == _inputStream) || string.IsNullOrEmpty(_outputPath))
        {
            if (null != _unzipCallback)
                _unzipCallback.OnFinished(false);

            return false;
        }

        // 创建文件目录
        if (!Directory.Exists(_outputPath))
            Directory.CreateDirectory(_outputPath);

        // 解压Zip包
        ZipEntry entry = null;
        using (ZipInputStream zipInputStream = new ZipInputStream(_inputStream))
        {
            if (!string.IsNullOrEmpty(_password))
                zipInputStream.Password = _password;

            while (null != (entry = zipInputStream.GetNextEntry()))
            {
                if (string.IsNullOrEmpty(entry.Name))
                    continue;

                if ((null != _unzipCallback) && !_unzipCallback.OnPreUnzip(entry))
                    continue;   // 过滤

                string filePathName = Path.Combine(_outputPath, entry.Name);

                // 创建文件目录
                if (entry.IsDirectory)
                {
                    Directory.CreateDirectory(filePathName);
                    continue;
                }

                // 写入文件
                try
                {
                    using (FileStream fileStream = File.Create(filePathName))
                    {
                        byte[] bytes = new byte[1024];
                        while (true)
                        {
                            int count = zipInputStream.Read(bytes, 0, bytes.Length);
                            if (count > 0)
                                fileStream.Write(bytes, 0, count);
                            else
                            {
                                if (null != _unzipCallback)
                                    _unzipCallback.OnPostUnzip(entry);

                                break;
                            }
                        }
                    }
                }
                catch (System.Exception _e)
                {
                    Debug.LogError("[ZipUtility.UnzipFile]: " + _e.ToString());

                    if (null != _unzipCallback)
                        _unzipCallback.OnFinished(false);

                    return false;
                }
            }
        }

        if (null != _unzipCallback)
            _unzipCallback.OnFinished(true);

        return true;
    }

    /// <summary>
    /// 压缩文件
    /// </summary>
    /// <param name="_filePathName">文件路径名</param>
    /// <param name="_parentRelPath">要压缩的文件的父相对文件夹</param>
    /// <param name="_zipOutputStream">压缩输出流</param>
    /// <param name="_zipCallback">ZipCallback对象,负责回调</param>
    /// <returns></returns>
    private static bool ZipFile(string _filePathName, string _parentRelPath, ZipOutputStream _zipOutputStream, ZipCallback _zipCallback = null)
    {

        //Crc32 crc32 = new Crc32();
        ZipEntry entry = null;
        FileStream fileStream = null;
        try
        {
            string entryName = _parentRelPath + '/' + Path.GetFileName(_filePathName);
            entry = new ZipEntry(entryName);
            entry.DateTime = System.DateTime.Now;

            if ((null != _zipCallback) && !_zipCallback.OnPreZip(entry))
                return true;    // 过滤

            fileStream = File.OpenRead(_filePathName);
            byte[] buffer = new byte[fileStream.Length];
            fileStream.Read(buffer, 0, buffer.Length);
            fileStream.Close();

            entry.Size = buffer.Length;

            //crc32.Reset();
            //crc32.Update(buffer);
            //entry.Crc = crc32.Value;

            _zipOutputStream.PutNextEntry(entry);
            _zipOutputStream.Write(buffer, 0, buffer.Length);
        }
        catch (System.Exception _e)
        {
            Debug.LogError("[ZipUtility.ZipFile]: " + _e.ToString());
            return false;
        }
        finally
        {
            if (null != fileStream)
            {
                fileStream.Close();
                fileStream.Dispose();
            }
        }

        if (null != _zipCallback)
            _zipCallback.OnPostZip(entry);

        return true;
    }

    /// <summary>
    /// 压缩文件夹
    /// </summary>
    /// <param name="_path">要压缩的文件夹</param>
    /// <param name="_parentRelPath">要压缩的文件夹的父相对文件夹</param>
    /// <param name="_zipOutputStream">压缩输出流</param>
    /// <param name="_zipCallback">ZipCallback对象,负责回调</param>
    /// <returns></returns>
    private static bool ZipDirectory(string _path, string _parentRelPath, ZipOutputStream _zipOutputStream, ZipCallback _zipCallback = null)
    {
        ZipEntry entry = null;
        try
        {
            string entryName = Path.Combine(_parentRelPath, Path.GetFileName(_path) + '/');
            entry = new ZipEntry(entryName);
            entry.DateTime = System.DateTime.Now;
            entry.Size = 0;

            if ((null != _zipCallback) && !_zipCallback.OnPreZip(entry))
                return true;    // 过滤

            _zipOutputStream.PutNextEntry(entry);
            _zipOutputStream.Flush();

            string[] files = Directory.GetFiles(_path);
            for (int index = 0; index < files.Length; ++index)
            {
                // 排除Unity中可能的 .meta 文件
                if (files[index].EndsWith(".meta")==true)
                {
                    Debug.LogWarning(files[index] + " not to zip");
                    continue;
                }

                ZipFile(files[index], Path.Combine(_parentRelPath, Path.GetFileName(_path)), _zipOutputStream, _zipCallback);
            }
        }
        catch (System.Exception _e)
        {
            Debug.LogError("[ZipUtility.ZipDirectory]: " + _e.ToString());
            return false;
        }

        string[] directories = Directory.GetDirectories(_path);
        for (int index = 0; index < directories.Length; ++index)
        {
            if (!ZipDirectory(directories[index], Path.Combine(_parentRelPath, Path.GetFileName(_path)), _zipOutputStream, _zipCallback))
            {
                return false;
            }
        }

        if (null != _zipCallback)
            _zipCallback.OnPostZip(entry);

        return true;
    }
}

 

  • 8
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
一次性训练多个大脑,需要使用Unity的Multi-Agent Reinforcement Learning(MARL)环境。在MARL环境中,多个智能体可以同时学习,从而提高协作和竞争能力。 训练命令: 使用Unity的MLagents-learn命令来启动训练。在训练命令中,需要指定训练的配置文件和场景文件,以及训练使用的算法和超参数等信息。 例如,在Windows系统中,使用以下命令来启动训练: ``` mlagents-learn config/trainer_config.yaml --env=envs/3DBall --num-envs=3 ``` 上述命令中,trainer_config.yaml是训练配置文件,envs/3DBall是场景文件,num-envs=3表示启动3个训练实例。 配置文件: 在训练配置文件中,需要指定训练的算法、智能体数量、智能体的观测和动作空间、训练的超参数等信息。 例如,在trainer_config.yaml配置文件中,可以使用以下代码来指定两个智能体: ``` default: trainer: ppo batch_size: 1024 beta: 5.0e-3 buffer_size: 512 epsilon: 0.2 gamma: 0.99 hidden_units: 128 lambd: 0.95 learning_rate: 3.0e-4 max_steps: 3.0e7 memory_size: 256 normalize: true num_epoch: 3 num_layers: 2 time_horizon: 64 sequence_length: 64 summary_freq: 5000 use_recurrent: false vis_encode_type: simple vis_encode_width: 84 vis_encode_height: 84 num_agents: 2 ``` 上述代码中,num_agents参数指定有两个智能体,其他参数可以根据具体需求进行修改。 总之,要一次性训练多个大脑,需要在MARL环境中使用MLagents-learn命令,并在训练配置文件中指定多个智能体的相关信息。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仙魁XAN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值