Skip entry stream on dispose

Until now the caller had to completely consume each entry stream, or call SkipEntry(), before disposing the stream. If not, exception was thrown: "EntryStream has not been fully consumed". Hugely inconvenient; a user-thrown exception inside a "using (EntryStream)" block would be discarded.

Now automatically skips the entry on dispose.

Added method EntryStream.Cancel(). Call this if entry stream is unfinished, and no further entries are required. Helps with efficiency, as it avoids reading data that is not needed.
This commit is contained in:
Paul Newman
2015-07-15 13:44:20 +01:00
parent 9eb43156e8
commit afff386622
4 changed files with 37 additions and 6 deletions

View File

@@ -236,7 +236,7 @@ namespace SharpCompress.Archive.SevenZip
protected override EntryStream GetEntryStream()
{
return new EntryStream(new ReadOnlySubStream(currentStream, currentItem.Size));
return CreateEntryStream(new ReadOnlySubStream(currentStream, currentItem.Size));
}
}
}

View File

@@ -26,12 +26,27 @@ namespace SharpCompress.Common
completed = true;
}
public bool Cancelled { get; private set; }
/// <summary>
/// Indicates that the remainder of the stream is not required.
/// On dispose, the entry will not be skipped, so it helps with efficiency.
/// The downside is that subsequent entries are not usable, as the compressed stream is not positioned at an entry boundary.
/// </summary>
public void Cancel()
{
if (!completed)
{
Cancelled = true;
stream.Close();
}
}
protected override void Dispose(bool disposing)
{
if (!completed)
if (!(completed || Cancelled))
{
throw new InvalidOperationException(
"EntryStream has not been fully consumed. Read the entire stream or use SkipEntry.");
SkipEntry();
}
if (isDisposed)
{

View File

@@ -77,6 +77,12 @@ namespace SharpCompress.Reader
{
return LoadStreamForReading(RequestInitialStream());
}
if (currentEntryStream != null && currentEntryStream.Cancelled)
{
throw new InvalidOperationException("EntryStream has not been fully consumed. Read the entire stream or use SkipEntry.");
}
if (!wroteCurrentEntry)
{
SkipEntry();
@@ -197,9 +203,19 @@ namespace SharpCompress.Reader
return stream;
}
private EntryStream currentEntryStream;
/// <summary>
/// Retains a reference to the entry stream, so we can check whether it completed later.
/// </summary>
protected EntryStream CreateEntryStream(Stream decompressed)
{
return currentEntryStream = new EntryStream(decompressed);
}
protected virtual EntryStream GetEntryStream()
{
return new EntryStream(Entry.Parts.First().GetCompressedStream());
return CreateEntryStream(Entry.Parts.First().GetCompressedStream());
}
#endregion

View File

@@ -73,7 +73,7 @@ namespace SharpCompress.Reader.Rar
protected override EntryStream GetEntryStream()
{
return new EntryStream(new RarStream(pack, Entry.FileHeader,
return CreateEntryStream(new RarStream(pack, Entry.FileHeader,
new MultiVolumeReadOnlyStream(
CreateFilePartEnumerableForCurrentEntry().Cast<RarFilePart>(), this)));
}