a .NET library that can read/write Office formats without Microsoft Office installed. No COM+, no interop.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
4.3 KiB

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections;
using ICSharpCode.SharpZipLib.Zip;
namespace NPOI.OpenXml4Net.Util
{
/**
* Provides a way to get at all the ZipEntries
* from a ZipInputStream, as many times as required.
* Allows a ZipInputStream to be treated much like
* a ZipFile, for a price in terms of memory.
* Be sure to call {@link #close()} as soon as you're
* done, to free up that memory!
*/
public class ZipInputStreamZipEntrySource : ZipEntrySource
{
private List<FakeZipEntry> zipEntries;
/**
* Reads all the entries from the ZipInputStream
* into memory, and closes the source stream.
* We'll then eat lots of memory, but be able to
* work with the entries at-will.
*/
public ZipInputStreamZipEntrySource(ZipInputStream inp)
{
zipEntries = new List<FakeZipEntry>();
bool going = true;
if(inp.Position != 0)
inp.Position = 0;
while (going)
{
ZipEntry zipEntry = inp.GetNextEntry();
if (zipEntry == null)
{
going = false;
}
else
{
FakeZipEntry entry = new FakeZipEntry(zipEntry, inp);
//inp.Close();
zipEntries.Add(entry);
}
}
inp.Close();
}
public IEnumerator Entries
{
get
{
return new EntryEnumerator(zipEntries);
}
}
public Stream GetInputStream(ZipEntry zipEntry)
{
FakeZipEntry entry = (FakeZipEntry)zipEntry;
return entry.GetInputStream();
}
public void Close()
{
// Free the memory
zipEntries = null;
}
public bool IsClosed
{
get { return zipEntries == null; }
}
/**
* Why oh why oh why are Iterator and Enumeration
* still not compatible?
*/
internal sealed class EntryEnumerator : IEnumerator
{
private List<FakeZipEntry>.Enumerator iterator;
internal EntryEnumerator(List<FakeZipEntry> zipEntries)
{
iterator = zipEntries.GetEnumerator();
}
public bool MoveNext()
{
return iterator.MoveNext();
}
public object Current
{
get
{
return iterator.Current;
}
}
#region IEnumerator Members
public void Reset()
{
throw new NotImplementedException();
}
#endregion
}
/**
* So we can close the real zip entry and still
* effectively work with it.
* Holds the (decompressed!) data in memory, so
* close this as soon as you can!
*/
public class FakeZipEntry : ZipEntry
{
private byte[] data;
public FakeZipEntry(ZipEntry entry, ZipInputStream inp) : base(entry.Name)
{
// Grab the de-compressed contents for later
MemoryStream baos = new MemoryStream();
long entrySize = entry.Size;
if (entrySize != -1)
{
if (entrySize >= Int32.MaxValue)
{
throw new IOException("ZIP entry size is too large");
}
baos = new MemoryStream((int)entrySize);
}
else
{
baos = new MemoryStream();
}
byte[] buffer = new byte[4096];
int read = 0;
while ((read = inp.Read(buffer, 0, buffer.Length)) > 0)
{
baos.Write(buffer, 0, read);
}
data = baos.ToArray();
}
public Stream GetInputStream()
{
return new MemoryStream(data);
}
}
}
}