0

次の方法を使用して、dotnetzip を使用して XML ファイルを zip に保存しようとしています。

    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();
    }

次に、次のメソッドを使用して XML ファイルを読み込みます。

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;
    }

ただし、このメソッドは、e.Extract(ms) 呼び出しで ZlibException -- Bad state (無効な格納ブロック長) -- をスローします。これが機能することをかなり確信で​​きるように、十分なドキュメントと例を読みましたが、これは dotnetzip を使用するのも初めてなので...これを解決する方法について何か考えはありますか?

4

1 に答える 1

0

あなたが何をしているのかよくわかりません.zip作成フェーズでm_repoがどのように作成されているのかわかりません。複雑すぎるようです。ジッパーの取出し部分も同様です。奇妙な方法で zip を作成した可能性があり、その結果、解凍エラーが発生します。コードがすべてではないため、わかりません。

単純化すれば、おそらくこれらの問題を回避できると思います。

次のようなデータ転送オブジェクト クラスがあるとします。

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; }
}

このコードは、エントリとして zip ファイルに格納されている XML 表現を使用して、zip ファイル (ストリームに保存) を作成します。

    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);

その後、同じメモリ ストリームからアンパックする場合は、次のようにします。

    Scrilla unpacked;
    // unzip:
    using (var zip2 = ZipFile.Read(zipStream))
    {
        Stream s = zip2[FILENAME_HOST].OpenReader();
        unpacked = (Scrilla) ser.Deserialize(new StreamReader(s));
    }

そして、それが機能したことを証明するために:

    // 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);
    }

作成時に、上記のコードは、 WriteDelegate を受け入れる ZipFile.AddEntry オーバーロードを使用しますWriteDelegate は、エントリ名とそのエントリのコンテンツを書き込むストリームを指定して ZipFile.Save() で呼び出される関数です。詳細については、DotNetZip のドキュメントを確認してください。ご覧のとおり、この WriteDelegate は、オブジェクトをそのストリームにラップされたストリームライターに XML シリアル化するだけです。

アンパックもショートカットを取ります - 読み取り可能なストリームから読み取るだけです。

いずれの場合も、作成してシークする必要がある余分なメモリストリームはありません。

このコードは私のために働いた。

これで問題が解決しない場合は、さらに詳細を提供してください。

于 2011-05-24T23:21:23.580 に答える