diff --git a/README.md b/README.md index f921241..a092345 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,36 @@ using (ArchiveFile archiveFile = new ArchiveFile(@"Archive.ARJ")) ``` +#### Alternative multi-extraction pattern: +```cs +using (ArchiveFile archiveFile = new ArchiveFile(@"Archive.ARJ")) +{ + byte[] backingArray = null; + MemoryStream outStr = null; + Entry entry = null; + Stream before(Entry _entry) + { + if (_entry.IsFolder || _entry.Size < 1) + return null; + entry = _entry; + backingArray = new byte[_entry.Size]; + outStr = new MemoryStream(backingArray); + return outStr; + } + void after(OperationResult opRes) + { + if (opRes == OperationResult.kOK) + { + // do whatever with Entry and extracted data + } + outStr.Dispose(); + backingArray = null; + } + archiveFile.Extract(before, after); +} + +``` + #### Guess archive format from files without extensions ```cs using (ArchiveFile archiveFile = new ArchiveFile(@"c:\random-archive")) diff --git a/SevenZipExtractor/ArchiveFile.cs b/SevenZipExtractor/ArchiveFile.cs index af4b47f..79dd92a 100644 --- a/SevenZipExtractor/ArchiveFile.cs +++ b/SevenZipExtractor/ArchiveFile.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices; +using static SevenZipExtractor.ArchiveStreamsCallbackEx; namespace SevenZipExtractor { @@ -95,6 +96,63 @@ public void Extract(string outputFolder, bool overwrite = false) }); } + public void Extract(Func getOutputStream) + { + IList fileStreams = new List(); + + try + { + foreach (Entry entry in Entries) + { + var outputStream = getOutputStream(entry); + + if (outputStream == null) + { + fileStreams.Add(null); + continue; + } + if (entry.IsFolder) + { + fileStreams.Add(null); + continue; + } + fileStreams.Add(outputStream); + } + + archive.Extract(null, 0xFFFFFFFF, 0, new ArchiveStreamsCallback(fileStreams)); + } + finally + { + } + } + + public void Extract(Func before, Action after) + { + IList operations = new List(); + try + { + foreach (Entry entry in Entries) + { + var op = new Operation() + { + Entry = entry, + Before = before, + After = after + }; + if (entry.IsFolder) + { + operations.Add(null); + continue; + } + operations.Add(op); + } + archive.Extract(null, 0xFFFFFFFF, 0, new ArchiveStreamsCallbackEx(operations)); + } + finally + { + } + } + public void Extract(Func getOutputPath) { IList fileStreams = new List(); diff --git a/SevenZipExtractor/ArchiveStreamsCallbackEx.cs b/SevenZipExtractor/ArchiveStreamsCallbackEx.cs new file mode 100644 index 0000000..1efa864 --- /dev/null +++ b/SevenZipExtractor/ArchiveStreamsCallbackEx.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace SevenZipExtractor +{ + internal class ArchiveStreamsCallbackEx : IArchiveExtractCallback + { + private readonly IList operations; + + public class Operation + { + public Entry Entry { get; set; } + public Func Before { get; set; } + public Action After { get; set; } + } + + public ArchiveStreamsCallbackEx(IList operations) + { + this.operations = operations; + } + + public void SetTotal(ulong total) + { + } + + public void SetCompleted(ref ulong completeValue) + { + } + + public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode) + { + if (askExtractMode != AskMode.kExtract) + { + outStream = null; + return 0; + } + + if (operations == null) + { + outStream = null; + return 0; + } + + Operation op = operations[(int)index]; + if (op == null) + { + outStream = null; + return 0; + } + var stream = op.Before(op.Entry); + if (stream == null) + { + outStream = null; + return 0; + } + + currentOperation = op; + + outStream = new OutStreamWrapper(stream); + + return 0; + } + + public void PrepareOperation(AskMode askExtractMode) + { + } + + private Operation currentOperation; + + public void SetOperationResult(OperationResult resultEOperationResult) + { + currentOperation?.After(resultEOperationResult); + currentOperation = null; + } + } +} \ No newline at end of file diff --git a/SevenZipExtractor/SevenZipExtractor.csproj b/SevenZipExtractor/SevenZipExtractor.csproj index 0bec929..4466546 100644 --- a/SevenZipExtractor/SevenZipExtractor.csproj +++ b/SevenZipExtractor/SevenZipExtractor.csproj @@ -41,6 +41,7 @@ + diff --git a/SevenZipExtractor/SevenZipInterface.cs b/SevenZipExtractor/SevenZipInterface.cs index 4237804..7526c6b 100644 --- a/SevenZipExtractor/SevenZipInterface.cs +++ b/SevenZipExtractor/SevenZipInterface.cs @@ -143,7 +143,7 @@ internal enum AskMode : int kSkip } - internal enum OperationResult : int + public enum OperationResult : int { kOK = 0, kUnSupportedMethod,