//IFS工具处理 处理 public void DoResIFSPackage(BuildTarget target, IFSCompressType ct = IFSCompressType.None, bool firstInclude = false, bool mergeLua = false, string luaZipName = "") { //SVN 版本号 string svnVersion = EditorSvnHelper.DoSvnInfoRivision(JW.Res.FileUtil.CombinePaths(Application.dataPath, "Resources")); //合并Lua脚本 if (mergeLua && (!string.IsNullOrEmpty(luaZipName))) { IFSArchiver.ArchiveDir(JW.Res.FileUtil.CombinePaths(_ifsBuildPath, GetPlatformStr(target), "LuaScripts"), JW.Res.FileUtil.CombinePaths(_ifsBuildPath, GetPlatformStr(target), luaZipName), IFSCompressType.None); //删除散lua 脚本 JW.Res.FileUtil.DeleteDirectory(JW.Res.FileUtil.CombinePaths(_ifsBuildPath, GetPlatformStr(target), "LuaScripts")); } //生成文件列表 IFSTool.GenerateFileList(JW.Res.FileUtil.CombinePath(_ifsBuildPath, GetPlatformStr(target)), _ifsFileListName, svnVersion); string dd = JW.Res.FileUtil.CombinePath(_ifsBuildPath, GetPlatformStr(target)); string zipPath = JW.Res.FileUtil.CombinePath(_ifsBuildPath, _ifsZipFileName); IFSTool.GenerateFirstIFSFile(zipPath, dd, ct); if (firstInclude) { //copy IFSTool.MoveFirstIFSFileToStreamingAssets(zipPath); } //移动Zip到原本目录 if (JW.Res.FileUtil.IsFileExist(zipPath)) { string fileName = JW.Res.FileUtil.GetFullName(zipPath); string dir = JW.Res.FileUtil.CombinePath(_ifsBuildPath, GetPlatformStr(target)); string dstPath = JW.Res.FileUtil.CombinePath(dir, _ifsZipFileName); JW.Res.FileUtil.MoveFile(zipPath, dstPath); } }
/// <summary> /// 归档一个目录成一个ifs /// </summary> /// <param name="dirPath"></param> /// <returns></returns> public static bool ArchiveDir(string indir, string outPath, IFSCompressType compress = IFSCompressType.None) { if (!FileUtil.IsDirectoryExist(indir)) { JW.Common.Log.LogE("IFSArchiver ArchiveDir-->Not Exist WorkDir:" + indir); return(false); } //不压缩直接归档 if (compress == IFSCompressType.None) { //获取所有文件 过滤svn string[] files = Directory.GetFiles(indir, "*", SearchOption.AllDirectories); if (files == null || files.Length == 0) { JW.Common.Log.LogE("IFSArchiver ArchiveDir-->No File In WorkDir:" + indir); return(false); } List <string> needfiles = new List <string>(); for (int i = 0; i < files.Length; i++) { string path = files[i]; string ext = FileUtil.GetExtension(path); if (ext.StartsWith(".svn") || ext.StartsWith(".meta")) { continue; } needfiles.Add(path); } return(DoArchiveDir(needfiles.ToArray(), indir, outPath, IFSCompressType.None)); } //需要压缩处理 if (compress == IFSCompressType.LZMA) { //获取所有文件 过滤 string[] files = Directory.GetFiles(indir, "*", SearchOption.AllDirectories); if (files == null || files.Length == 0) { JW.Common.Log.LogE("IFSArchiver ArchiveDir-->No File In WorkDir:" + indir); return(false); } string tempDir = FileUtil.GetFullDirectory(outPath); tempDir = FileUtil.CombinePaths(tempDir, "IFSLZMATemp"); if (FileUtil.IsDirectoryExist(tempDir)) { FileUtil.ClearDirectory(tempDir); } else { FileUtil.CreateDirectory(tempDir); } //压缩所有归档文件到临时目录 try { for (int i = 0; i < files.Length; i++) { string path = files[i]; string ext = FileUtil.GetExtension(path); if (ext.StartsWith(".svn")) { continue; } //压缩 string relativePath = FileUtil.GetRelativePath(files[i], indir); string tempPath = FileUtil.CombinePaths(tempDir, relativePath); //原本是相对路径 创建对应目录 string directory = Path.GetDirectoryName(tempPath); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } JW.Common.Log.LogD("---LZMA--->" + relativePath); CompressFileLZMAToFile(files[i], tempPath); } } catch (Exception exp) { JW.Common.Log.LogE("Archive Exception With LZMA:" + exp.ToString()); return(false); } //合并 string[] realfiles = Directory.GetFiles(tempDir, "*", SearchOption.AllDirectories); bool isOk = DoArchiveDir(realfiles, tempDir, outPath, IFSCompressType.LZMA); //删除临时目录 FileUtil.DeleteDirectory(tempDir); JW.Common.Log.LogD("Done!"); return(isOk); } return(true); }
//归档一批文件 private static bool DoArchiveDir(string[] needfiles, string indir, string outPath, IFSCompressType compressType) { if (needfiles == null || needfiles.Length == 0) { return(false); } // int fileCnt = needfiles.Length; // IFSFile ifsFile = new IFSFile(); ifsFile.EntryCount = fileCnt; ifsFile.CompressType = compressType; ifsFile.Entrys = new IFSEntry[fileCnt]; for (int i = 0; i < fileCnt; i++) { ifsFile.Entrys[i] = new IFSEntry(); } // //初始化条目 for (int i = 0; i < fileCnt; i++) { IFSEntry entry = ifsFile.Entrys[i]; string relativePath = FileUtil.GetRelativePath(needfiles[i], indir); entry.Name = relativePath; entry.DataSize = FileUtil.GetFileLength(needfiles[i]); } int entryNameSegL = 0; //写入开始 int begin = 0; //签名 begin += 4; //压缩方式 begin += 4; //条目个数 begin += 4; //条目名字段长度 begin += 4; //条目名称信息 for (int i = 0; i < ifsFile.Entrys.Length; i++) { IFSEntry entry = ifsFile.Entrys[i]; int l = GetStringBytesLength(entry.Name); begin += l; entryNameSegL += l; } //条目数据位置段 for (int i = 0; i < ifsFile.Entrys.Length; i++) { begin += 4; } //设置 for (int i = 0; i < ifsFile.Entrys.Length; i++) { IFSEntry entry = ifsFile.Entrys[i]; if (i == 0) { entry.DataPos = begin; } else { IFSEntry entryPre = ifsFile.Entrys[i - 1]; //数据开始位置是上一个的开始位置+4+L entry.DataPos = entryPre.DataPos + 4 + entryPre.DataSize; } } //开始写 //写大文件 FileStream outIfs = new FileStream(outPath, FileMode.Create); //先写入文件头签名 byte[] bb = ConvertIntToBytes((int)ifsFile.Signature); outIfs.Write(bb, 0, bb.Length); //写入压缩方式 bb = ConvertIntToBytes((int)ifsFile.CompressType); outIfs.Write(bb, 0, bb.Length); //条目个数 bb = ConvertIntToBytes(ifsFile.Entrys.Length); outIfs.Write(bb, 0, bb.Length); //条目名称总长度 bb = ConvertIntToBytes(entryNameSegL); outIfs.Write(bb, 0, bb.Length); //条目名字信息 for (int i = 0; i < ifsFile.Entrys.Length; i++) { IFSEntry entry = ifsFile.Entrys[i]; byte[] bbs = ConvertStringToBytes(entry.Name); //名字 outIfs.Write(bbs, 0, bbs.Length); } //条目数据位置开始位置索引写入 for (int i = 0; i < ifsFile.Entrys.Length; i++) { IFSEntry entry = ifsFile.Entrys[i]; byte[] bbs = ConvertIntToBytes(entry.DataPos); //名字 outIfs.Write(bbs, 0, bbs.Length); } try { //写入所有文件数据 for (int i = 0; i < ifsFile.Entrys.Length; i++) { IFSEntry entry = ifsFile.Entrys[i]; //长度 byte[] ddl = ConvertIntToBytes(entry.DataSize); outIfs.Write(ddl, 0, ddl.Length); //写入数据 byte[] fileData = FileUtil.ReadFile(needfiles[i]); outIfs.Write(fileData, 0, entry.DataSize); } } catch (Exception exc) { JW.Common.Log.LogE("Archive Exception:" + exc.ToString()); return(false); } outIfs.Flush(); outIfs.Close(); return(true); }
/// <summary> /// 生成IFS 的首次Zip包 /// </summary> /// <param name="ifsBuildDir"></param> /// <param name="firstName"></param> public static void GenerateFirstIFSFile(string firstNamePath, string ifsBuildDir, IFSCompressType tt = IFSCompressType.None) { if (!JW.Res.FileUtil.IsDirectoryExist(ifsBuildDir)) { JW.Common.Log.LogE("Dir Not Exist:" + ifsBuildDir); } IFSArchiver.ArchiveDir(ifsBuildDir, firstNamePath, tt); }
private bool Init() { //分析备用 int totalL = (int)_stream.Length; if (totalL < 20) { JW.Common.Log.LogE("IFSFile InitWithData Error IFS File Length"); return(false); } //获取签名 byte[] bbs = new byte[16]; int offset = 0; _stream.Read(bbs, 0, 16); uint sig = (uint)IFSArchiver.ConvertBytesToInt(bbs, ref offset); if (sig != IFSFile.IFSSignature) { JW.Common.Log.LogE("IFSFile InitWithData Error Signature "); return(false); } this.Signature = sig; //获取压缩方式 this.CompressType = (IFSCompressType)IFSArchiver.ConvertBytesToInt(bbs, ref offset); //条目个数 this.EntryCount = IFSArchiver.ConvertBytesToInt(bbs, ref offset); //名称长度 int entryNameL = IFSArchiver.ConvertBytesToInt(bbs, ref offset); if (this.EntryCount == 0) { JW.Common.Log.LogE("IFSFile InitWithData Error EntryCount"); return(false); } //条目名称段 this.Entrys = new IFSEntry[this.EntryCount]; this._entryDic = new JWObjDictionary <string, IFSEntry>(this.EntryCount); for (int i = 0; i < this.EntryCount; i++) { this.Entrys[i] = new IFSEntry(); } // bbs = null; // byte[] names = new byte[entryNameL]; _stream.Read(names, 0, entryNameL); offset = 0; //读取条目名称 for (int i = 0; i < this.EntryCount; i++) { IFSEntry entry = this.Entrys[i]; entry.Name = IFSArchiver.ConvertBytesToString(names, ref offset); if (_entryDic.ContainsKey(entry.Name)) { JW.Common.Log.LogE("IFSFile Repeat Entry:" + entry.Name); } else { _entryDic.Add(entry.Name, entry); } } //条目数据位置 offset = 0; names = null; byte[] poss = new byte[this.EntryCount * 4]; _stream.Read(poss, 0, this.EntryCount * 4); for (int i = 0; i < this.EntryCount; i++) { IFSEntry entry = this.Entrys[i]; int vv = IFSArchiver.ConvertBytesToInt(poss, ref offset); entry.DataPos = vv; } offset = 0; poss = null; return(true); }