zip/gzip skipping now doesn't involve decompression https://github.com/simmotech/sharpcompress

This commit is contained in:
Adam Hathcock
2013-04-28 11:07:13 +01:00
parent 0331cae916
commit ab9155dfc5
20 changed files with 85 additions and 37 deletions

1
.gitignore vendored
View File

@@ -4,3 +4,4 @@ _ReSharper.SharpCompress/
bin/
*.suo
TestArchives/Scratch/
TestArchives/Scratch2/

View File

@@ -17,7 +17,7 @@ namespace SharpCompress.Archive.GZip
public virtual Stream OpenEntryStream()
{
return Parts.Single().GetStream();
return Parts.Single().GetCompressedStream();
}
#region IArchiveEntry Members

View File

@@ -21,7 +21,7 @@ namespace SharpCompress.Archive.Rar
private set;
}
internal override Stream GetStream()
internal override Stream GetCompressedStream()
{
var stream = volume.Stream;
stream.Position = FileHeader.DataStartPosition;

View File

@@ -18,7 +18,7 @@ namespace SharpCompress.Archive.Rar
private set;
}
internal override Stream GetStream()
internal override Stream GetCompressedStream()
{
Stream.Position = FileHeader.DataStartPosition;
return Stream;

View File

@@ -17,7 +17,7 @@ namespace SharpCompress.Archive.SevenZip
public Stream OpenEntryStream()
{
return Parts.Single().GetStream();
return Parts.Single().GetCompressedStream();
}
public void WriteTo(Stream stream)

View File

@@ -16,7 +16,7 @@ namespace SharpCompress.Archive.Tar
public virtual Stream OpenEntryStream()
{
return Parts.Single().GetStream();
return Parts.Single().GetCompressedStream();
}
#region IArchiveEntry Members

View File

@@ -16,7 +16,7 @@ namespace SharpCompress.Archive.Zip
public virtual Stream OpenEntryStream()
{
return Parts.Single().GetStream();
return Parts.Single().GetCompressedStream();
}
#region IArchiveEntry Members

View File

@@ -5,6 +5,8 @@ namespace SharpCompress.Common
{
public abstract class Entry : SharpCompress.Common.IEntry
{
internal bool IsSolid { get; set; }
/// <summary>
/// The File's 32 bit CRC Hash
/// </summary>

View File

@@ -9,6 +9,7 @@ namespace SharpCompress.Common
get;
}
internal abstract Stream GetStream();
internal abstract Stream GetCompressedStream();
internal abstract Stream GetRawStream();
}
}

View File

@@ -9,12 +9,12 @@ namespace SharpCompress.Common.GZip
internal class GZipFilePart : FilePart
{
private string name;
private Stream stream;
private readonly Stream stream;
internal GZipFilePart(Stream stream)
{
ReadAndValidateGzipHeader(stream);
this.stream = new DeflateStream(stream, CompressionMode.Decompress, CompressionLevel.Default, false);
this.stream = stream;
}
internal DateTime? DateModified { get; private set; }
@@ -24,15 +24,18 @@ namespace SharpCompress.Common.GZip
get { return name; }
}
internal override Stream GetStream()
internal override Stream GetCompressedStream()
{
return new DeflateStream(stream, CompressionMode.Decompress, CompressionLevel.Default, false);
}
internal override Stream GetRawStream()
{
return stream;
}
private void ReadAndValidateGzipHeader(Stream stream)
{
int totalBytesRead = 0;
// read the header on the first read
byte[] header = new byte[10];
int n = stream.Read(header, 0, header.Length);
@@ -49,19 +52,18 @@ namespace SharpCompress.Common.GZip
Int32 timet = BitConverter.ToInt32(header, 4);
DateModified = TarHeader.Epoch.AddSeconds(timet);
totalBytesRead += n;
if ((header[3] & 0x04) == 0x04)
{
// read and discard extra field
n = stream.Read(header, 0, 2); // 2-byte length field
totalBytesRead += n;
Int16 extraLength = (Int16)(header[0] + header[1] * 256);
byte[] extra = new byte[extraLength];
n = stream.Read(extra, 0, extra.Length);
if (n != extraLength)
{
throw new ZlibException("Unexpected end-of-file reading GZIP header.");
totalBytesRead += n;
}
}
if ((header[3] & 0x08) == 0x08)
name = ReadZeroTerminatedString(stream);
@@ -72,7 +74,7 @@ namespace SharpCompress.Common.GZip
}
private string ReadZeroTerminatedString(Stream stream)
private static string ReadZeroTerminatedString(Stream stream)
{
byte[] buf1 = new byte[1];
var list = new System.Collections.Generic.List<byte>();
@@ -82,13 +84,16 @@ namespace SharpCompress.Common.GZip
// workitem 7740
int n = stream.Read(buf1, 0, 1);
if (n != 1)
{
throw new ZlibException("Unexpected EOF reading GZIP header.");
}
if (buf1[0] == 0)
{
done = true;
}
else
{
if (buf1[0] == 0)
done = true;
else
list.Add(buf1[0]);
list.Add(buf1[0]);
}
} while (!done);
byte[] a = list.ToArray();

View File

@@ -1,4 +1,5 @@
using SharpCompress.Common.Rar.Headers;
using System.IO;
using SharpCompress.Common.Rar.Headers;
namespace SharpCompress.Common.Rar
{
@@ -24,5 +25,10 @@ namespace SharpCompress.Common.Rar
get;
private set;
}
internal override Stream GetRawStream()
{
return null;
}
}
}

View File

@@ -22,7 +22,7 @@ namespace SharpCompress.Common.SevenZip
get { return Header.Name; }
}
internal override Stream GetStream()
internal override Stream GetCompressedStream()
{
if (!Header.HasStream)
{
@@ -36,6 +36,11 @@ namespace SharpCompress.Common.SevenZip
return new ReadOnlySubStream(stream, (long)Header.Size);
}
internal override Stream GetRawStream()
{
return null;
}
public CompressionType CompressionType
{
get

View File

@@ -20,7 +20,7 @@ namespace SharpCompress.Common.Tar
get { return Header.Name; }
}
internal override Stream GetStream()
internal override Stream GetCompressedStream()
{
if (seekableStream != null)
{
@@ -29,5 +29,10 @@ namespace SharpCompress.Common.Tar
}
return Header.PackedStream;
}
internal override Stream GetRawStream()
{
return null;
}
}
}

View File

@@ -14,14 +14,14 @@ namespace SharpCompress.Common.Zip
this.headerFactory = headerFactory;
}
internal override Stream GetStream()
internal override Stream GetCompressedStream()
{
if (!isLocalHeaderLoaded)
{
LoadLocalHeader();
isLocalHeaderLoaded = true;
}
return base.GetStream();
return base.GetCompressedStream();
}
internal string Comment

View File

@@ -19,7 +19,7 @@ namespace SharpCompress.Common.Zip
return Header.PackedStream;
}
internal override Stream GetStream()
internal override Stream GetCompressedStream()
{
if (!Header.HasData)
{
@@ -43,7 +43,7 @@ namespace SharpCompress.Common.Zip
{
if (decompressionStream == null)
{
decompressionStream = GetStream();
decompressionStream = GetCompressedStream();
}
decompressionStream.SkipAll();

View File

@@ -29,7 +29,7 @@ namespace SharpCompress.Common.Zip
get { return Header.Name; }
}
internal override Stream GetStream()
internal override Stream GetCompressedStream()
{
if (!Header.HasData)
{
@@ -43,6 +43,15 @@ namespace SharpCompress.Common.Zip
return decompressionStream;
}
internal override Stream GetRawStream()
{
if (!Header.HasData)
{
return Stream.Null;
}
return CreateBaseStream();
}
protected abstract Stream CreateBaseStream();
protected bool LeaveStreamOpen

View File

@@ -55,7 +55,7 @@ namespace SharpCompress.Compressor.Rar
{
currentStream.Dispose();
}
currentStream = filePartEnumerator.Current.GetStream();
currentStream = filePartEnumerator.Current.GetCompressedStream();
currentPartTotalReadBytes = 0;

View File

@@ -136,12 +136,28 @@ namespace SharpCompress.Reader
}
}
internal void Skip()
readonly byte[] skipBuffer = new byte[4096];
private void Skip()
{
var buffer = new byte[4096];
using (Stream s = OpenEntryStream())
if (!Entry.IsSolid)
{
while (s.Read(buffer, 0, buffer.Length) > 0)
var rawStream = Entry.Parts.First().GetRawStream();
if (rawStream != null)
{
var bytesToAdvance = Entry.CompressedSize;
for (var i = 0; i < bytesToAdvance / skipBuffer.Length; i++)
{
rawStream.Read(skipBuffer, 0, skipBuffer.Length);
}
rawStream.Read(skipBuffer, 0, (int)(bytesToAdvance % skipBuffer.Length));
return;
}
}
using (var s = OpenEntryStream())
{
while (s.Read(skipBuffer, 0, skipBuffer.Length) > 0)
{
}
}
@@ -183,7 +199,7 @@ namespace SharpCompress.Reader
protected virtual EntryStream GetEntryStream()
{
return new EntryStream(Entry.Parts.First().GetStream());
return new EntryStream(Entry.Parts.First().GetCompressedStream());
}
#endregion

View File

@@ -11,7 +11,7 @@ namespace SharpCompress.Reader.Rar
{
}
internal override Stream GetStream()
internal override Stream GetCompressedStream()
{
return FileHeader.PackedStream;
}

View File

@@ -13,8 +13,6 @@ namespace SharpCompress.Reader.Rar
IsSolid = solid;
}
internal bool IsSolid { get; private set; }
internal RarFilePart Part { get; private set; }
internal override IEnumerable<FilePart> Parts