如何在C#中直接读取ZIP文件中的XML文件?

时间:2011-03-06 00:05:23

标签: c# .net xml zip

在Java中,您可以传递类似“zip:zip_file!xml_file”的URL,它将使用zip文件中指定的XML文件.XmlUrlResolver没有此功能。有没有办法做到这一点?

2 个答案:

答案 0 :(得分:4)

有一个开源解决方案。 (xml reports处的XmlZipResolver代码。)它继承自XmlUrlResolver以添加此功能。

实际上这很简单。 XmlZipResolver类继承自XmlUrlResolver。因此,在创建XmlUrlResolver对象以访问XML文件之前,您可以创建一个XmlZipResolver对象,然后可以像处理XmlUrlResolver对象一样对待它。这适用于XmlUrlResolver只有在url以zip:或jar:(Java jar文件是zip文件)开头时才使用附加代码处理的任何URL。

关键部分是调用GetEntity,它将打开zip文件,然后获取zip文件中所请求的xml文件的流。此代码使用SharpZipLib进行所有zip文件访问。

在此之后,一切都非常简单,所有对成员函数的调用都从嵌入式xml文件的流中返回。因为GetEntity()返回一个对象,如果它返回一个基本的XmlUrlResolver对象,则不会调用此类中的方法。因此,所有剩余的成员函数都是专门为zip文件的情况编写的。

另一项不是返回的Stream是一个包含三个对象的对象,ZipFile,作为zip文件的Stream,以及作为zip条目的流。此返回的对象继承自Stream。对于除Close()之外的每个调用,它只是将相同的调用传递给zip条目流对象。但是在关闭(因此间接在Dispose上),它会关闭所有三个对象。

再次,xml reports的XmlZipResolver代码。

答案 1 :(得分:4)

以下是我使用ICSharpCode.SharpZipLib的一些代码:

public bool Process()
    {
        var importFile = new FileInfo("c:\\foo\myzip.zip");
        var success = true;
        using (var zipStream = new ZipInputStream(importFile.OpenRead()))
        {
            ZipEntry theEntry;
            while ((theEntry = zipStream.GetNextEntry()) != null)
            {
                var lowerName = theEntry.Name.ToLower();

                try
                {

                    if (lowerName.EndsWith(".xml") && !lowerName.StartsWith("__macosx"))
                    {

                        var doc = new XmlDocument();
                        doc.Load(zipStream);
                    }
                }
                catch (Exception e)
                {
                    success = false;
                    Log.Error(string.Format("Error parsing {0} ERROR {1}",lowerName,e.Message));
                }

            }
        }
        return success;
    }

这将处理zip中的每个xml文件...除了突然出现的愚蠢的Mac OsX元文件:)