关于Unity Zip文件解压缩设计
unity中可能会使用到Zip文件解压缩的操作
例如:Unity Editor环境下,解压缩文件 到unity Assets 文件路劲下,再对解压缩文件进一步操作!
解压缩的方法
- DotNetZip
- 7-Zip
- 其他(无非调用解压缩内核)
DotNetZip示例
using AXClipperLib;
using Ionic.Zip;
using JUN.Xmpp.Iq.Privacy;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
using Action = System.Action;
public class DotNetZip : Singleton<DotNetZip>
{
internal void UnpackPackage(string filename, string folder)
{
var ok = CheckZipIsOK(filename);//检查Zip文件是否正确
string[] importExtensions = { ".obj", ".fbx", ".dae",".prefab" };//需要额外操作的文件 文件扩展名
if (ok)
{
using (ZipFile file = new ZipFile(filename, Encoding.UTF8))
{
file.FlattenFoldersOnExtract = false;
var status = new StringWriter();
file.StatusMessageTextWriter = status;
//记录需要额外操作文件的文件路径
List<string> modelFileList = new List<string>();
List<string> prefebFileList = new List<string>();
//取出不需要操作的其他文件
foreach (var entry in file.Entries)
{
string name = entry.FileName.ToLowerInvariant();
if (!importExtensions.Any(e => { return name.EndsWith(e); }))
entry.Extract(folder, ExtractExistingFileAction.OverwriteSilently);
}
//取出需要操作的文件
foreach (var entry in file.Entries)
{
string name = entry.FileName.ToLowerInvariant();
if (name.EndsWith(".obj") || name.EndsWith(".fbx") || name.EndsWith(".dae"))
{
entry.Extract(folder, ExtractExistingFileAction.OverwriteSilently);
modelFileList.Add(folder + entry.FileName);
}
if (name.EndsWith(".prefab"))
{
entry.Extract(folder, ExtractExistingFileAction.OverwriteSilently);
prefebFileList.Add(folder + entry.FileName);
}
}
//文件预操作
foreach (var item in modelFileList)
{
//DoSomeThing(item);
}
foreach (var item in prefebFileList)
{
//DoSomeThing(item);
}
}
}
//刷新
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
//解决关于文件命解压缩不区分大小写导致的覆盖问题!(好像没有差别)
internal string UnpackPackageStream(string filename, string folder)
{
var ok = CheckZipIsOK(filename);//检查Zip文件是否正确
string[] importExtensions = { ".obj", ".fbx", ".dae",".prefab" };//需要额外操作的文件 文件扩展名
if (ok)
{
using (ZipInputStream stream = new ZipInputStream(filename))
{
var status = new StringWriter();
ZipEntry entry;
List<ZipEntry> modelZipEntryList = new List<ZipEntry>();
List<ZipEntry> prefebZipEntryList = new List<ZipEntry>();
while ((entry = stream.GetNextEntry()) != null)
{
string name = entry.FileName.ToLowerInvariant();
if (!importExtraProceessExtensions.Any(e => { return name.EndsWith(e); }))
{
entry.Extract(folder, ExtractExistingFileAction.OverwriteSilently);
}
if (name.EndsWith(".prefab"))
{
entry.Extract(folder, ExtractExistingFileAction.OverwriteSilently);
prefebZipEntryList.Add(entry);
}
if (name.EndsWith(".obj"))
{
entry.Extract(folder, ExtractExistingFileAction.OverwriteSilently);
modelZipEntryList.Add(entry);
}
}
foreach (var e in modelZipEntryList)
{
//DoSomeThing(item);
}
foreach (var e in prefebZipEntryList)
{
//DoSomeThing(item);
}
}
}
else
{
UnityEngine.Debug.Log("Package is not OK, not processing");
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
string tempPath = "D:/Temp/Unpackage/";
string tempUnityPath = "Assets/" + "Temp/";
//解压缩到临时文件夹中先
internal string UnpackPackageTemp(string filename, string folder)
{
DeleteAndCreateDirectory(tempPath);
DeleteAndCreateDirectory(Path.GetFullPath(tempUnityPath));
var ok = CheckZipIsOK(filename);
string[] importExtensions = { ".obj", ".fbx", ".dae",".prefab" };//需要额外操作的文件 文件扩展名
if (ok)
{
using (ZipFile file = new ZipFile(filename, Encoding.UTF8))
{
file.FlattenFoldersOnExtract = false;
var status = new StringWriter();
file.StatusMessageTextWriter = status;
List<string> modelFileList = new List<string>();
List<string> prefebFileList = new List<string>();
//file ExtractAll
foreach (var entry in file.Entries)
{
string name = entry.FileName.ToLowerInvariant();
if (!importExtraProceessExtensions.Any(e => { return name.EndsWith(e); }))
entry.Extract(tempPath, ExtractExistingFileAction.OverwriteSilently);
}
foreach (var entry in file.Entries)
{
string name = entry.FileName.ToLowerInvariant();
if (name.EndsWith(".obj") || name.EndsWith(".fbx") || name.EndsWith(".dae"))
{
entry.Extract(tempPath, ExtractExistingFileAction.OverwriteSilently);
modelFileList.Add(tempPath + entry.FileName);
}
if (name.EndsWith(".prefab"))
{
entry.Extract(tempPath, ExtractExistingFileAction.OverwriteSilently);
prefebFileList.Add(tempPath + entry.FileName);
}
}
foreach (var item in prefebFileList)
{
var tempPath;
//存在部分文件,需要在unity环境中,转换生成新类型文件,
//处理生成文件放置Unity 临时文件夹中。操作玩后,将生成新文件转移到外部临时文件夹目标位置。
TempUnityEditorCreator(item, tempPath, (string fileName, string oriengeFileName) =>
{
//Do some thing
});
}
AssetDatabase.Refresh();
for (int i = 0; i < modelFileList.Count; i++) 处理生成文件
{
//存在部分文件,需要在unity 环境中修改参数
//转移到unity环境中
//操作
//新文件覆盖回去
TempUnityEditorCreator(modelFileList[i], (string filePath) =>
{
//Do some thing
});
}
}
}
else
{
UnityEngine.Debug.Log("Package is not OK, not processing");
}
AssetDatabase.DeleteAsset(folder);
AssetDatabase.DeleteAsset(tempUnityPath);
Directory.Move(tempPath, folder);//解压缩文件,移动到Unity路径下
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private void DeleteAndCreateDirectory(string directoryPath, bool createNew = true)
{
if (string.IsNullOrEmpty(directoryPath))
{
return;
}
if (Directory.Exists(directoryPath))
{
try
{
Directory.Delete(directoryPath, true);
}
catch (Exception e)
{
UnityEngine.Debug.Log("Failed to delete the UnpackedData folder for " + e.Message + " Rename it to root folder to delete.");
string name = DateTime.Now.ToFileTime().ToString();
Directory.Move(directoryPath + "data\\Assets\\", "U:\\Tmp\\");
Directory.Delete(directoryPath, true);
try
{
Directory.Delete("U:\\Tmp\\", true);
}
catch (Exception ex)
{
UnityEngine.Debug.Log("Still Failed to delete the UnpackedData folder for " + ex.Message + " Rename it to aovid blocking.");
Directory.Move("U:\\Tmp\\", "U:\\Temp\\" + name + "\\");
}
}
}
if (createNew)
{
Directory.CreateDirectory(directoryPath);
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private void TempUnityEditorCreator(string fileName, string oriengeFileName, Action<string, string> active)
{
//do something to create file in unity directory
var _fileName = Path.GetFileName(fileName);
var _tempUnityFilePath = tempUnityPath + _fileName;
active(fileName, _tempUnityFilePath);
//move new create file to direction file
File.Copy(_tempUnityFilePath, oriengeFileName, true);
}
private void TempUnityEditorCreator(string fileName, Action<string> active)
{
//copy file to unity directory
var _fileName = Path.GetFileName(fileName);
var _tempUnityFilePath = tempUnityPath + _fileName;
if (!File.Exists(_tempUnityFilePath))
{
File.Create(_tempUnityFilePath).Dispose();
}
File.Copy(fileName, _tempUnityFilePath, true);
AssetDatabase.Refresh();
//do some thing
active(_tempUnityFilePath);
//move back newer file
File.Copy(_tempUnityFilePath, fileName, true);
}
}
7-Zip 示例
在这里插入代码片
注意
一、 DotNetZip文件解压缩存在如下问题
- 解压缩文件名过长
- 解压缩强制文件名小写(存在文件相互覆盖)
二、Unity AssetDatabase 刷新问题
- 丢失关联问题
当文件解压缩时,我们可能需要在AssetDatabase refresh前预操作
当文件间存在相互引用关系,如果refresh后,再预操作,可能丢失关联!
这就需要我们控制解压缩操作中仔细检查别AssetDatabase refresh操作
但这很难
提供个思路:
我们先提前解压缩到Assets 外部的临时文件夹中,
再对临时文件夹文件预操作,
最后再移回Unity文件夹中