public LpkOutputStream(Stream lpk, LpkFileInfo file) { this.baseStream = lpk; this.info = file; baseStream.Position = file.DataOffset; gzip = new GZipStream(baseStream, CompressionMode.Decompress, true); }
/// <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); } }
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; }
/// <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); }
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>()); }
/// <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(); } }