internal readonly ZipArchiveMode mode;
internal Encoding entryNameEncoding;
internal bool disposed;
- internal Dictionary<string, ZipArchiveEntry> entries;
+ internal List<ZipArchiveEntry> entries;
internal SharpCompress.Archive.Zip.ZipArchive zipFile;
public ZipArchive (Stream stream)
this.stream = stream;
mode = ZipArchiveMode.Read;
- CreateZip(stream, mode);
+ CreateZip(mode);
}
public ZipArchive (Stream stream, ZipArchiveMode mode)
this.stream = stream;
this.mode = mode;
- CreateZip(stream, mode);
+ CreateZip(mode);
}
public ZipArchive (Stream stream, ZipArchiveMode mode, bool leaveOpen)
this.stream = stream;
this.mode = mode;
leaveStreamOpen = leaveOpen;
- CreateZip(stream, mode);
+ CreateZip(mode);
}
public ZipArchive (Stream stream, ZipArchiveMode mode, bool leaveOpen, Encoding entryNameEncoding)
this.mode = mode;
leaveStreamOpen = leaveOpen;
this.entryNameEncoding = entryNameEncoding;
- CreateZip(stream, mode);
+ CreateZip(mode);
}
- private void CreateZip(Stream stream, ZipArchiveMode mode)
+ private void CreateZip(ZipArchiveMode mode)
{
- if (mode != ZipArchiveMode.Read && mode != ZipArchiveMode.Create && mode != ZipArchiveMode.Update)
- throw new ArgumentOutOfRangeException("mode");
+ try {
+ if (mode != ZipArchiveMode.Read && mode != ZipArchiveMode.Create && mode != ZipArchiveMode.Update)
+ throw new ArgumentOutOfRangeException("mode");
- // If the mode parameter is set to Read, the stream must support reading.
- if (mode == ZipArchiveMode.Read && !stream.CanRead)
- throw new ArgumentException("Stream must support reading for Read archive mode");
+ // If the mode parameter is set to Read, the stream must support reading.
+ if (mode == ZipArchiveMode.Read && !stream.CanRead)
+ throw new ArgumentException("Stream must support reading for Read archive mode");
- // If the mode parameter is set to Create, the stream must support writing.
- if (mode == ZipArchiveMode.Create && !stream.CanWrite)
- throw new ArgumentException("Stream must support writing for Create archive mode");
+ // If the mode parameter is set to Create, the stream must support writing.
+ if (mode == ZipArchiveMode.Create && !stream.CanWrite)
+ throw new ArgumentException("Stream must support writing for Create archive mode");
- // If the mode parameter is set to Update, the stream must support reading, writing, and seeking.
- if (mode == ZipArchiveMode.Update && (!stream.CanRead || !stream.CanWrite || !stream.CanSeek))
- throw new ArgumentException("Stream must support reading, writing and seeking for Update archive mode");
+ // If the mode parameter is set to Update, the stream must support reading, writing, and seeking.
+ if (mode == ZipArchiveMode.Update && (!stream.CanRead || !stream.CanWrite || !stream.CanSeek))
+ throw new ArgumentException("Stream must support reading, writing and seeking for Update archive mode");
- try {
- zipFile = mode == ZipArchiveMode.Create ?
- SharpCompress.Archive.Zip.ZipArchive.Create() :
- SharpCompress.Archive.Zip.ZipArchive.Open(stream);
- } catch (Exception) {
- throw new InvalidDataException("The contents of the stream are not in the zip archive format.");
- }
+ // If the stream is not seekable, then buffer it into memory (same behavior as .NET).
+ if (mode == ZipArchiveMode.Read && !stream.CanSeek)
+ {
+ var memoryStream = new MemoryStream();
+ stream.CopyTo(memoryStream);
- entries = new Dictionary<string, ZipArchiveEntry>();
- if (Mode != ZipArchiveMode.Create) {
- foreach (var entry in zipFile.Entries) {
- var zipEntry = new ZipArchiveEntry(this, entry);
- entries[entry.Key] = zipEntry;
+ if (!leaveStreamOpen)
+ stream.Dispose();
+
+ this.stream = memoryStream;
}
+
+ try {
+ zipFile = mode != ZipArchiveMode.Create && stream.Length != 0
+ ? SharpCompress.Archive.Zip.ZipArchive.Open(stream)
+ : SharpCompress.Archive.Zip.ZipArchive.Create();
+ } catch (Exception e) {
+ throw new InvalidDataException("The contents of the stream are not in the zip archive format.", e);
+ }
+
+ entries = new List<ZipArchiveEntry>();
+ if (Mode != ZipArchiveMode.Create) {
+ foreach (var entry in zipFile.Entries) {
+ var zipEntry = new ZipArchiveEntry(this, entry);
+ entries.Add(zipEntry);
+ }
+ }
+ }
+ catch {
+ if (!leaveStreamOpen)
+ stream.Dispose();
+ throw;
}
}
if (entries == null)
return new ReadOnlyCollection<ZipArchiveEntry>(new List<ZipArchiveEntry>());
- return new ReadOnlyCollection<ZipArchiveEntry>(entries.Values.ToList());
+ return new ReadOnlyCollection<ZipArchiveEntry>(entries);
}
}
return CreateEntry(entryName, CompressionLevel.Optimal);
}
+ internal SharpCompress.Archive.Zip.ZipArchiveEntry CreateEntryInternal(string entryName)
+ {
+ var memoryStream = new MemoryStream();
+ var entry = zipFile.AddEntry(entryName, memoryStream);
+
+ return entry;
+ }
+
public ZipArchiveEntry CreateEntry (string entryName, CompressionLevel compressionLevel)
{
if (disposed)
if (zipFile == null)
throw new InvalidDataException("The zip archive is corrupt, and its entries cannot be retrieved.");
- var memoryStream = new MemoryStream();
- var entry = zipFile.AddEntry(entryName, memoryStream);
- var archiveEntry = new ZipArchiveEntry(this, entry);
- entries[entryName] = archiveEntry;
+ var internalEntry = CreateEntryInternal(entryName);
+ var archiveEntry = new ZipArchiveEntry(this, internalEntry);
+ entries.Add(archiveEntry);
return archiveEntry;
}
if (zipFile == null)
throw new InvalidDataException("The zip archive is corrupt, and its entries cannot be retrieved.");
- return entries.ContainsKey(entryName) ? entries[entryName] : null;
+ return entries.FirstOrDefault(e => e.FullName == entryName);
}
private void Save()
{
using (var newZip = new MemoryStream()) {
- zipFile.SaveTo(newZip, CompressionType.Deflate);
+ zipFile.SaveTo(newZip, CompressionType.Deflate, entryNameEncoding ?? Encoding.UTF8);
stream.SetLength(0);
stream.Position = 0;