Exemplo n.º 1
0
 public LpkOutputStream(Stream lpk, LpkFileInfo file)
 {
     this.baseStream     = lpk;
     this.info           = file;
     baseStream.Position = file.DataOffset;
     gzip = new GZipStream(baseStream, CompressionMode.Decompress, true);
 }
Exemplo n.º 2
0
        /// <summary>
        /// 从压缩包解压某文件到内存
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="progress">解压进度回调对象</param>
        /// <returns></returns>
        public MemoryStream OpenFile(string fileName, ICodeProgress progress)
        {
            lock (hashTable)
            {
                MemoryStream ms = new MemoryStream();
                fileStream.Position = hashTable[fileName];
                LpkFileInfo fileInfo = new LpkFileInfo(fileStream);
                fileStream.Position = fileInfo.DataOffset;
                try
                {
                    LZMA.LzmaHelper.Decompress(fileStream, ms, fileInfo.FileSize, fileInfo.UncompressedSize, progress);
                }
                catch (Exception ex)
                {
                    Logger.Log.Error(ex);
                    throw new Exception(string.Format("File:{1} CRC({0:X}) error, file open failed!", fileInfo.CRC, fileName));
                }
                ms.Position = 0;

                uint crc = LZMA.LzmaHelper.CRC32(ms);
                if (fileInfo.CRC != crc)
                {
                    throw new Exception(string.Format("CRC(Original:{0:X} Current:{1:X}) error, file open failed!", fileInfo.CRC, crc));
                }

                ms.Position = 0;
                return(ms);
            }
        }
Exemplo n.º 3
0
 public LpkInputStream(Stream lpk, LpkFileInfo file)
 {
     this.baseStream     = lpk;
     this.info           = file;
     baseStream.Position = file.DataOffset;
     gzip                  = new GZipStream(baseStream, CompressionMode.Compress, true);
     file.FileSize         = 0;
     file.UncompressedSize = 0;
 }
Exemplo n.º 4
0
        /// <summary>
        /// 取得文件元信息
        /// </summary>
        /// <param name="name">文件名</param>
        /// <returns>元信息</returns>
        public LpkFileInfo GetInfo(string name)
        {
            fileStream.Position = hashTable[name];
            LpkFileInfo info = new LpkFileInfo(fileStream)
            {
                Name = name
            };

            return(info);
        }
Exemplo n.º 5
0
 private List <LpkFileInfo> GetInfos()
 {
     if (hashTable != null)
     {
         List <LpkFileInfo> list = new List <LpkFileInfo>();
         foreach (string i in hashTable.Keys)
         {
             fileStream.Position = hashTable[i];
             LpkFileInfo info = new LpkFileInfo(fileStream)
             {
                 Name = i
             };
             list.Add(info);
         }
         return(list);
     }
     return(new List <LpkFileInfo>());
 }
Exemplo n.º 6
0
        /// <summary>
        /// 向压缩包添加文件
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="inStream">要添加的文件的流</param>
        /// <param name="progress">压缩进度回调对象</param>
        public void AddFile(string fileName, Stream inStream, ICodeProgress progress)
        {
            lock (hashTable)
            {
                //元信息备份缓存
                byte[] metaBackup = new byte[LpkFileInfo.Size * hashTable.Count];
                uint   crc;
                //备份老哈希表偏移
                int oldHashOffset = hashOffset;

                BinaryWriter bwOri = new BinaryWriter(fileStream);
                uint         size, uncompressedSize;

                if (hashTable.ContainsKey(fileName))
                {
                    throw new ArgumentException("A file with this name(" + fileName + ") already exists!");
                }

                crc = LZMA.LzmaHelper.CRC32(inStream);
                inStream.Position = 0;
                //取得要添加的文件的原大小
                uncompressedSize = (uint)inStream.Length;

                //备份压缩包原元信息
                fileStream.Position = hashOffset + hashSize + 4;
                fileStream.Read(metaBackup, 0, LpkFileInfo.Size * hashTable.Count);

                //取得新哈希表大小
                hashTable.Add(fileName, 0);
                int newHashSize = HashBuffer.Length;

                //压缩并写入新加文件数据
                fileStream.Position = hashOffset;
                LZMA.LzmaHelper.Compress(inStream, fileStream, progress);
                //取得新加文件压缩后大小
                size = (uint)(fileStream.Position - hashOffset);
                //设置哈希表新偏移
                hashOffset = (int)fileStream.Position;

                //将备份的元信息写回文件,便于之后修正
                fileStream.Position += (newHashSize + 4);
                fileStream.Write(metaBackup, 0, metaBackup.Length);
                //将哈希表新偏移写回文件
                fileStream.Position = 4;
                bwOri.Write(hashOffset);

                //开始修正元数据
                fileStream.Position = hashOffset + 4 + newHashSize;
                string[] files = new string[hashTable.Count];
                hashTable.Keys.CopyTo(files, 0);

                foreach (string i in files)
                {
                    LpkFileInfo info;

                    if (i != fileName)
                    {
                        //修正文件元数据偏移
                        hashTable[i]       += ((hashOffset - oldHashOffset) + (newHashSize - hashSize));
                        fileStream.Position = hashTable[i];
                        info = new LpkFileInfo(fileStream)
                        {
                            HeaderOffset = (uint)hashTable[i]
                        };
                    }
                    else
                    {
                        //计算新文件元数据偏移
                        hashTable[i] = 4 + hashOffset + newHashSize + ((hashTable.Count - 1) * LpkFileInfo.Size);
                        info         = new LpkFileInfo()
                        {
                            //计算元数据信息
                            HeaderOffset     = (uint)hashTable[i],
                            DataOffset       = (uint)(oldHashOffset),
                            UncompressedSize = uncompressedSize,
                            CRC      = crc,
                            FileSize = size
                        };
                    }
                    //将修正后的元数据写回文件
                    info.WriteToStream(fileStream);
                }

                //将新哈希表写回文件
                fileStream.Position = hashOffset;
                bwOri.Write(newHashSize);
                bwOri.Write(Encrypt(HashBuffer));
                hashSize = newHashSize;

                infoBuf = GetInfos();
            }
        }