public IExtractor ExtractFiles(ulong[] indices, Func <ArchiveFile, Stream> onStreamRequest, Action <ArchiveFile, Stream> onStreamClose = null) { if (indices.Any(index => index >= (ulong)_Files.LongLength)) { throw new ArgumentOutOfRangeException("An index given in `indices[]` array is out of range."); } // preprocess files and keep track of streams to decompress var streamToFileIndex = new Dictionary <ulong, ulong>(); var streamIndices = new List <ulong>(); ulong streamIndex = 0; for (ulong i = 0; i < (ulong)_Files.LongLength; ++i) { if (!indices.Any() || Array.IndexOf(indices, i) != -1) { if (_Files[i].IsEmpty) { using (Stream s = onStreamRequest(_Files[i])) if (s != null) { onStreamClose?.Invoke(_Files[i], s); } } else if (indices.Any()) { streamIndices.Add(streamIndex); } } if (!_Files[i].IsEmpty) { streamToFileIndex[streamIndex++] = i; } } // no file to decompress if (!streamToFileIndex.Any()) { //Trace.TraceWarning("ExtractFiles: No decoding required."); return(this); } // progress provider SevenZipProgressProvider szpp = null; if (ProgressDelegate != null) { szpp = new SevenZipProgressProvider(_Files, indices, ProgressDelegate); } // extraction //Trace.TraceInformation("Extracting..."); var sx = new SevenZipStreamsExtractor(stream, header.RawHeader.MainStreamsInfo, Password); sx.ExtractMultiple( streamIndices.ToArray(), (ulong index) => onStreamRequest(_Files[streamToFileIndex[index]]), (ulong index, Stream stream) => onStreamClose?.Invoke(_Files[streamToFileIndex[index]], stream), szpp); return(this); }
public IExtractor ExtractFiles(ulong[] indices, string outputDirectory) { if (indices.Any(index => index >= (ulong)_Files.LongLength)) { throw new ArgumentOutOfRangeException("An index given in `indices[]` array is out of range."); } // preprocess files and keep track of streams to decompress var streamToFileIndex = new Dictionary <ulong, ulong>(); var streamIndices = new List <ulong>(); ulong streamIndex = 0; for (ulong i = 0; i < (ulong)_Files.LongLength; ++i) { if (!indices.Any() || Array.IndexOf(indices, i) != -1) { if (!preProcessFile(outputDirectory, _Files[i])) { streamIndices.Add(streamIndex); } } if (!_Files[i].IsEmpty) { streamToFileIndex[streamIndex++] = i; } } // no file to decompress if (!streamIndices.Any()) { //Trace.TraceWarning("ExtractFiles: No decoding required."); return(this); } // progress provider SevenZipProgressProvider szpp = null; if (ProgressDelegate != null) { szpp = new SevenZipProgressProvider(_Files, indices, ProgressDelegate); } // extraction //Trace.TraceInformation("Extracting..."); var sx = new SevenZipStreamsExtractor(stream, header.RawHeader.MainStreamsInfo, Password); sx.ExtractMultiple( streamIndices.ToArray(), (ulong index) => { SevenZipArchiveFile file = _Files[streamToFileIndex[index]]; string fullPath = Path.Combine(outputDirectory, PreserveDirectoryStructure ? file.Name : Path.GetFileName(file.Name)); //Trace.TraceInformation($"File index {index}, filename: {file.Name}, file size: {file.Size}"); return(new FileStream(fullPath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize)); }, (ulong index, Stream stream) => { stream.Close(); SevenZipArchiveFile file = _Files[streamToFileIndex[index]]; string fullPath = Path.Combine(outputDirectory, PreserveDirectoryStructure ? file.Name : Path.GetFileName(file.Name)); if (file.Time != null) { File.SetLastWriteTimeUtc(fullPath, (DateTime)file.Time); } }, szpp); return(this); }