public void Write(ArchiveListing listing, out ArchiveListingBlockInfo[] blocksInfo, out ArchiveListingEntryInfoV2[] entriesInfoV2) { using (MemoryStream ms = new MemoryStream(32768)) { int blockNumber = 0, unpackedBlockOffset = 0; entriesInfoV2 = new ArchiveListingEntryInfoV2[listing.Count]; List <ArchiveListingBlockInfo> blocks = new List <ArchiveListingBlockInfo>(128); using (FormattingStreamWriter sw = new FormattingStreamWriter(ms, Encoding.ASCII, 4096, true, CultureInfo.InvariantCulture)) { sw.AutoFlush = true; for (int i = 0; i < listing.Count; i++) { ArchiveEntry entry = listing[i]; ArchiveListingEntryInfoV2 info = new ArchiveListingEntryInfoV2 { BlockNumber = (short)(ms.Position / 8192) }; info.Flag = (info.BlockNumber % 2 != 0); entriesInfoV2[i] = info; if (blockNumber != info.BlockNumber) { int blockSize = (int)(ms.Position - unpackedBlockOffset); ms.Position = unpackedBlockOffset; ArchiveListingBlockInfo block = new ArchiveListingBlockInfo { Offset = (int)_output.Position, UncompressedSize = blockSize }; block.CompressedSize = ZLibHelper.Compress(ms, _output, block.UncompressedSize); blocks.Add(block); blockNumber++; unpackedBlockOffset = (int)ms.Position; sw.Write("{0:x}:{1:x}:{2:x}:{3}\0", entry.Sector, entry.UncompressedSize, entry.Size, entry.Name); } else if (i == listing.Count - 1) { info.Offset = (short)(ms.Position - unpackedBlockOffset); sw.Write("{0:x}:{1:x}:{2:x}:{3}\0end\0", entry.Sector, entry.UncompressedSize, entry.Size, entry.Name); int blockSize = (int)(ms.Position - unpackedBlockOffset); ms.Position = unpackedBlockOffset; ArchiveListingBlockInfo block = new ArchiveListingBlockInfo { Offset = (int)_output.Position, UncompressedSize = blockSize }; block.CompressedSize = ZLibHelper.Compress(ms, _output, block.UncompressedSize); blocks.Add(block); } else { info.Offset = (short)(ms.Position - unpackedBlockOffset); sw.Write("{0:x}:{1:x}:{2:x}:{3}\0", entry.Sector, entry.UncompressedSize, entry.Size, entry.Name); } } } blocksInfo = blocks.ToArray(); } }
public void OnWritingCompleted(ArchiveEntry entry, MemoryStream ms, bool?compression) { ms.Position = 0; int compressedSize = 0; int uncompressedSize = (int)ms.Length; byte[] copyBuff = new byte[Math.Min(uncompressedSize, 32 * 1024)]; try { bool compress = uncompressedSize > 256 && (compression ?? entry.IsCompressed); if (compress) { using (SafeUnmanagedArray buff = new SafeUnmanagedArray(uncompressedSize + 256)) using (UnmanagedMemoryStream buffStream = buff.OpenStream(FileAccess.ReadWrite)) { compressedSize = ZLibHelper.Compress(ms, buffStream, uncompressedSize); if (uncompressedSize - compressedSize > 256) { using (Stream output = OpenOrAppendBinary(entry, compressedSize)) { buffStream.Position = 0; buffStream.CopyToStream(output, compressedSize, copyBuff); } return; } } } ms.Position = 0; compressedSize = uncompressedSize; using (Stream output = OpenOrAppendBinary(entry, uncompressedSize)) ms.CopyToStream(output, uncompressedSize, copyBuff); } finally { entry.Size = compressedSize; entry.UncompressedSize = uncompressedSize; } }
private void UncompressBlocks(ArchiveListingBlockInfo[] blocks, Stream stream) { try { for (int i = 0; i < blocks.Length; i++) { ArchiveListingBlockInfo block = blocks[i]; int uncompressedSize = block.UncompressedSize; stream.Position = _header.InfoOffset + block.Offset; _uncompressedBlocks[i] = ZLibHelper.Uncompress(stream, uncompressedSize); } } catch (ObjectDisposedException) { } catch (Exception ex) { _exception = ex; } }
public static Stream BackgroundExtractIfCompressed(Stream input, ArchiveEntry entry) { if (!entry.IsCompressed) { return(input); } int uncompressedSize = (int)entry.UncompressedSize; if (uncompressedSize == 0) { return(new MemoryStream(0)); } Stream writer, reader; Flute.CreatePipe(uncompressedSize, out writer, out reader); //if (!ThreadPool.QueueUserWorkItem((o) => ZLibHelper.UncompressAndDisposeStreams(input, writer, uncompressedSize, CancellationToken.None))) ThreadHelper.StartBackground("UncompressAndDisposeSourceAsync", () => ZLibHelper.UncompressAndDisposeStreams(input, writer, uncompressedSize, CancellationToken.None)); return(reader); }