Dotnetzip bad state error when extracting a text/XML file
I am trying to store an XML file into a zip using dotnetzip using the following method:
private void writeHosts()
{
XmlRootAttribute root = new XmlRootAttribute(ROOTNAME_HOST);
XmlSerializer ser = new XmlSerializer(typeof(Host[]), root);
MemoryStream ms = new MemoryStream();
StreamWriter swriter = new StreamWriter(ms);
//write xml to memory stream
ser.Serialize(swriter, m_hostList.ToArray());
swriter.Flush();
//be kind, rewind (the stream)
ms.Seek(0, SeekOrigin.Begin);
//copy memory stream to zip as a file.
using (m_repo)
{
ZipEntry e = m_repo.AddEntry(FILENAME_HOST, ms);
e.IsText = true;
m_repo.Save();
}
swriter.Close();
}
I then read the XML file back in using this method:
private List<Host> readHosts()
{
XmlRootAttribute root = new XmlRootAttribute(ROOTNAME_HOST);
XmlSerializer ser = new XmlSerializer(typeof(Host[]), root);
MemoryStream ms = new MemoryStream();
StreamReader reader = new StreamReader(ms);
List<Host> retlist = new List<Host>();
//get the vuln list from the zip and read into memory
using (m_repo)
{
ZipEntry e = m_repo[FILENAME_HOST];
e.Extract(ms);
}
//rewind to the start of the stream
ms.Flush();
ms.Seek(0, SeekOrigin.Begin);
//Pull the host list from XML
Host[] ret = (Host[])ser.Deserialize(reader);
retlist.AddRange(ret);
ms.Close();
return retlist;
}
However, this method throws a ZlibException -- Bad state (invalid stored block lengths) -- at the e.Extract(ms) call. I've read through enough documentation and examples to be fairly certain that this should work, but this is also my first time working with dotnetzip so... any thoughts on how to resolve开发者_运维知识库 this?
I don't really get what you're doing, I don't see how m_repo is being created, in the zip creation phase. It looks like it's overly complicated. Also same thing in the zip extraction part. It's possible that you've created the zip in a way that is odd, which results in a decompression error. I can't tell because the code isn't all there.
I think if you simplify, you will probably avoid these problems.
Suppose a data-transfer-object class like this:
public class Scrilla
{
// the parts that get serialized:
[XmlElement]
public String Name { get;set; }
[XmlElement]
public DateTime FirstReport { get;set; }
[XmlElement]
public String MoreInfo { get;set; }
}
This code will create a zipfile (saved into a stream), with the XML representation of that thing stored in the zip file as an entry:
var FILENAME_HOST = "self.xml";
XmlRootAttribute root = new XmlRootAttribute("root");
XmlSerializer ser = new XmlSerializer(typeof(Scrilla), root);
MemoryStream zipStream = new MemoryStream();
var scrilla = new Scrilla
{
Name = "Foop",
FirstReport = DateTime.Now,
MoreInfo = "see http://example.org"
};
// zip up:
using (var zip1 = new ZipFile())
{
zip1.AddEntry(FILENAME_HOST,(entryName,stream) => {
using (var swriter = new StreamWriter(stream))
{
ser.Serialize(swriter, scrilla);
}});
zip1.Save(zipStream);
}
// the content (an XML file) is now held in the MemoryStream
zipStream.Seek(0, SeekOrigin.Begin);
If you then want to unpack from the same memory stream, you can do this:
Scrilla unpacked;
// unzip:
using (var zip2 = ZipFile.Read(zipStream))
{
Stream s = zip2[FILENAME_HOST].OpenReader();
unpacked = (Scrilla) ser.Deserialize(new StreamReader(s));
}
And then to prove that it worked:
// prove that it worked - print out to Console
var xmlws = new System.Xml.XmlWriterSettings { OmitXmlDeclaration = true, Indent= true };
using ( var w2 = System.Xml.XmlWriter.Create(Console.Out, xmlws))
{
ser.Serialize(w2, unpacked);
}
On creation the code above uses the ZipFile.AddEntry overload that accepts a WriteDelegate. The WriteDelegate is a function that is called upon ZipFile.Save() with the entry name and a stream into which you should write the content for that entry. Check the DotNetZip documentation for details. As you can see this WriteDelegate just XML-serializes an object into a streamwriter wrapped around that stream.
The unpacking also takes a shortcut - it just reads from a readable stream.
In each case there's no extra memorystream you need to create and seek through.
This code worked for me.
If this doesn't help you, maybe you could provide some more details.
精彩评论