Пример #1
0
 public void LogFileInfo()
 {
     if (Entrys != null)
     {
         for (int i = 0; i < this.EntryCount; i++)
         {
             IFSEntry e = Entrys[i];
             JW.Common.Log.LogD(e.Name);
         }
     }
 }
Пример #2
0
        //
        private static bool DoUnarchiveLZMAIFSFile(IFSFile ifsFile, string outDir, Stream fileS)
        {
            bool isOk = true;

            try
            {
                //公用buffer
                byte[] buffer = new byte[4 * 1024];
                int    offset = 0;
                //解压数据到文件
                for (int i = 0; i < ifsFile.EntryCount; i++)
                {
                    IFSEntry entry = ifsFile.Entrys[i];
                    JW.Common.Log.LogD("Un LZMA File:" + entry.Name);
                    //
                    fileS.Seek(entry.DataPos, SeekOrigin.Begin);
                    byte[] ll = new byte[4];
                    fileS.Read(ll, 0, 4);
                    offset = 0;
                    int vv = ConvertBytesToInt(ll, ref offset);
                    entry.DataSize = vv;
                    //解压
                    string outPath   = FileUtil.CombinePaths(outDir, entry.Name);
                    string directory = Path.GetDirectoryName(outPath);
                    if (!Directory.Exists(directory))
                    {
                        Directory.CreateDirectory(directory);
                    }
                    FileStream output = new FileStream(outPath, FileMode.Create);
                    try
                    {
                        SevenZip.Compression.LZMA.Decoder coder = new SevenZip.Compression.LZMA.Decoder();
                        byte[] properties = new byte[5];
                        fileS.Read(properties, 0, 5);
                        byte[] fileLengthBytes = new byte[8];
                        fileS.Read(fileLengthBytes, 0, 8);
                        long fileLength = BitConverter.ToInt64(fileLengthBytes, 0);
                        coder.SetDecoderProperties(properties);
                        coder.Code(fileS, output, entry.DataSize, fileLength, null);
                        output.Flush();
                    }
                    catch (Exception exc)
                    {
                        JW.Common.Log.LogE("LZMA Failed:" + entry.Name + "---" + exc.ToString());
                    }
                    finally
                    {
                        output.Close();
                        output.Dispose();
                        output = null;
                    }
                }
            }
            catch (Exception exc)
            {
                JW.Common.Log.LogE("LZMA Failed:" + exc.ToString());
                isOk = false;
            }
            finally
            {
                fileS.Close();
                fileS.Dispose();
            }
            return(isOk);
        }
Пример #3
0
        /// <summary>
        /// 同步解压一个IFS文件内存流
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="outDir"></param>
        /// <returns></returns>
        public static bool SyncUnarchiveIFSFile(MemoryStream fileS, string outDir)
        {
            if (FileUtil.IsDirectoryExist(outDir))
            {
                FileUtil.ClearDirectory(outDir);
            }
            else
            {
                FileUtil.CreateDirectory(outDir);
            }
            //
            JW.Common.Log.LogD("Begin->");
            Stopwatch st = new Stopwatch();

            st.Start();
            //
            IFSFile ifsFile = new IFSFile();

            //获取签名
            byte[] bbs    = new byte[16];
            int    offset = 0;

            fileS.Read(bbs, 0, 16);
            uint sig = (uint)ConvertBytesToInt(bbs, ref offset);

            if (sig != IFSFile.IFSSignature)
            {
                JW.Common.Log.LogE("IFSArchiver SyncUnarchiveIFSFile Error Signature ");
                fileS.Close();
                return(false);
            }
            ifsFile.Signature = sig;
            //获取压缩方式
            ifsFile.CompressType = (IFSCompressType)ConvertBytesToInt(bbs, ref offset);
            //条目个数
            ifsFile.EntryCount = ConvertBytesToInt(bbs, ref offset);
            //名称长度
            int entryNameL = ConvertBytesToInt(bbs, ref offset);

            if (ifsFile.EntryCount == 0)
            {
                JW.Common.Log.LogE("IFSArchiver SyncUnarchiveIFSFile Error  EntryCount");
                fileS.Close();
                return(false);
            }
            //条目名称段
            ifsFile.Entrys = new IFSEntry[ifsFile.EntryCount];
            for (int i = 0; i < ifsFile.EntryCount; i++)
            {
                ifsFile.Entrys[i] = new IFSEntry();
            }
            //
            bbs = null;
            //
            byte[] names = new byte[entryNameL];
            fileS.Read(names, 0, entryNameL);
            offset = 0;
            //读取条目名称
            for (int i = 0; i < ifsFile.EntryCount; i++)
            {
                IFSEntry entry = ifsFile.Entrys[i];
                entry.Name = ConvertBytesToString(names, ref offset);
            }
            //条目数据位置
            offset = 0;
            names  = null;
            byte[] poss = new byte[ifsFile.EntryCount * 4];
            fileS.Read(poss, 0, ifsFile.EntryCount * 4);
            for (int i = 0; i < ifsFile.EntryCount; i++)
            {
                IFSEntry entry = ifsFile.Entrys[i];
                int      vv    = ConvertBytesToInt(poss, ref offset);
                entry.DataPos = vv;
            }
            offset = 0;
            poss   = null;
            #region 无压缩 直接解压
            //无压缩 直接解压
            if (ifsFile.CompressType == IFSCompressType.None)
            {
                bool isOk = false;
                try
                {
                    //公用buffer
                    byte[] buffer = new byte[4 * 1024];
                    //解压数据到文件
                    for (int i = 0; i < ifsFile.EntryCount; i++)
                    {
                        IFSEntry entry     = ifsFile.Entrys[i];
                        string   outPath   = FileUtil.CombinePaths(outDir, entry.Name);
                        string   directory = Path.GetDirectoryName(outPath);
                        if (!Directory.Exists(directory))
                        {
                            Directory.CreateDirectory(directory);
                        }
                        FileStream output = new FileStream(outPath, FileMode.Create);
                        try
                        {
                            fileS.Seek(entry.DataPos, SeekOrigin.Begin);
                            byte[] ll = new byte[4];
                            fileS.Read(ll, 0, 4);
                            offset = 0;
                            int vv = ConvertBytesToInt(ll, ref offset);
                            entry.DataSize = vv;
                            //
                            bool copying   = true;
                            int  processed = 0;
                            while (copying)
                            {
                                int bytesRead = fileS.Read(buffer, 0, buffer.Length);
                                if (bytesRead > 0)
                                {
                                    if (entry.DataSize <= bytesRead)
                                    {
                                        output.Write(buffer, 0, entry.DataSize);
                                        copying = false;
                                    }
                                    else
                                    {
                                        processed += bytesRead;
                                        if (processed > entry.DataSize)
                                        {
                                            output.Write(buffer, 0, bytesRead - (processed - entry.DataSize));
                                            copying = false;
                                        }
                                        else
                                        {
                                            output.Write(buffer, 0, bytesRead);
                                            copying = true;
                                        }
                                    }
                                }
                                else
                                {
                                    copying = false;
                                }
                            }
                            //
                            output.Flush();
                        }
                        catch (Exception exc)
                        {
                            JW.Common.Log.LogE("Failed:" + entry.Name + "---" + exc.ToString());
                        }
                        finally
                        {
                            output.Close();
                            output.Dispose();
                            output = null;
                        }
                    }
                }
                catch (Exception exc)
                {
                    JW.Common.Log.LogE("IFSArchiver SyncUnarchiveIFSFile:" + exc.ToString());
                    isOk = false;
                }
                finally
                {
                    st.Stop();//终止计时
                    JW.Common.Log.LogD("Done:" + st.ElapsedMilliseconds.ToString());
                    fileS.Close();
                    fileS.Dispose();
                    fileS = null;
                }
                st.Stop();//终止计时
                JW.Common.Log.LogD("Done:" + st.ElapsedMilliseconds.ToString());
                return(isOk);
            }
            #endregion
            //
            if (ifsFile.CompressType == IFSCompressType.LZMA)
            {
                bool isOk = DoUnarchiveLZMAIFSFile(ifsFile, outDir, fileS);
                st.Stop();
                JW.Common.Log.LogD("Done:" + st.ElapsedMilliseconds.ToString());
                return(isOk);
            }
            return(true);
        }
Пример #4
0
        //归档一批文件
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        /// <summary>
        /// 获取条目数据
        /// </summary>
        /// <param name="name">条目名称</param>
        /// <returns></returns>
        public byte[] GetEntryData(string name)
        {
            if (this.CompressType == IFSCompressType.LZMA)
            {
                JW.Common.Log.LogE("IFSFile GetEntryData Error No Support LZMA Entry TODO");
                return(null);
            }

            if (this.EntryCount <= 0)
            {
                JW.Common.Log.LogE("IFSFile GetEntryData Error No Init");
                return(null);
            }

            if (_stream == null)
            {
                JW.Common.Log.LogE("IFSFile GetEntryData Error No Init");
                return(null);
            }

            IFSEntry find = null;

            if (!_entryDic.TryGetValue(name, out find))
            {
                find = null;
            }
            //for (int i = 0; i < this.EntryCount; i++)
            //{
            //    IFSEntry e = Entrys[i];
            //    if (e.Name.Equals(name))
            //    {
            //        find = e;
            //        break;
            //    }
            //}
            if (find == null)
            {
                JW.Common.Log.LogE("IFSFile GetEntryData Error No Entry :" + name);
                return(null);
            }

            if (find.Data != null)
            {
                return(find.Data);
            }
            //读取
            _stream.Seek(find.DataPos, SeekOrigin.Begin);
            byte[] ll = new byte[4];
            _stream.Read(ll, 0, 4);
            int offset = 0;
            int vv     = IFSArchiver.ConvertBytesToInt(ll, ref offset);

            find.DataSize = vv;
            //
            if (vv == 0)
            {
                JW.Common.Log.LogE("IFSFile GetEntryData Error No Entry Data:" + name);
                return(null);
            }
            byte[] buffer = new byte[vv];
            _stream.Read(buffer, 0, buffer.Length);
            //
            find.Data = buffer;
            //
            return(buffer);
        }