【问题标题】:getting "Stream Was Not Writable" while saving an XML document that I read via a stream from a zip file在保存我通过 zip 文件中的流读取的 XML 文档时获取“流不可写”
【发布时间】:2012-08-07 22:15:46
【问题描述】:

我有一个包含 xml 文件的 zip 文件, 我正在将此 xml 文件加载到 xml 文档中,而无需提取文件。 这是通过流完成的。 这样做之后,我正在修改一些节点的内部文本。 问题是我在尝试保存流后遇到了前面提到的异常,代码如下:

(我在这里使用 DotNetZip

ZipFile zipFile = ZipFile.Read(zipPath); // the path is my desktop
foreach (ZipEntry entry in zipFile)
{
  if (entry.FileName == "myXML.xml")
  { 
    //creating the stream and loading the xml doc from the zip file:
    Stream stream = zipFile[entry.FileName].OpenReader();    
    XmlReader xReader = XmlReader.Create(stream);
    XmlDocument xDoc = new XmlDocument();
    xDoc.Load(xReader);

    //changing the inner text of the doc nodes:
    xDoc.DocumentElement.SelectSingleNode("Account/Name").InnerText = "VeXe";
    xDoc.DocumentElement.SelectSingleNode("Account/Money").InnerText = "Million$";

    xDoc.Save(stream); // here's where I got the exception.
    break;
  }
}

我不是专业编码人员,但我注意到它也可以将XmlWriter 作为参数而不是xDoc.Save(stream);,因此我尝试在实例化 XmlReader 后立即创建 XmlWriter 的实例 ..
我试过这样做:xDoc.Save(XmlWriter) 我遇到了一个例外,比如:“阅读后无法写作”

我怎样才能成功保存 xDoc ?

添加: 我有一个想法,将 xml 文件保存在其他地方,比如临时文件夹或其他地方 然后在 zip 中添加该保存的文件,覆盖旧文件,然后删除 temp 中的 xml 文件。 但这不是我想要的,我想直接处理 zip 文件,进出,没有第三方。

【问题讨论】:

    标签: c# xml stream dotnetzip


    【解决方案1】:

    您正尝试写入您打开它时使用的同一个 Stream。你不能那样做。

    也许可以试试这样的:

    ZipFile zipFile = ZipFile.Read(zipPath); // the path is my desktop
    foreach (ZipEntry entry in zipFile)
    {
        if (entry.FileName == "myXML.xml")
        { 
            //creating the stream and loading the xml doc from the zip file:
            using (Stream stream = zipFile[entry.FileName].OpenReader()) {
                XmlReader xReader = XmlReader.Create(stream);
                XmlDocument xDoc = new XmlDocument();
                xDoc.Load(xReader);
            }
    
            //changing the inner text of the doc nodes:
            xDoc.DocumentElement.SelectSingleNode("Account/Name").InnerText = "VeXe";
            xDoc.DocumentElement.SelectSingleNode("Account/Money").InnerText = "Million$";
    
            using (StreamWriter streamWriter = new StreamWriter(pathToSaveTo)) {
                xDoc.Save(streamWriter); 
                break;
            }
        }
    }
    

    【讨论】:

    • 我在我的问题中添加了我想直接处理 zip 文件,我不想将 xml 保存到其他地方,然后将其添加回 zip 文件。
    • 无论哪种方式,您都需要先关闭阅读流,然后再继续打开写入流。
    【解决方案2】:

    一个快速的look at the docs 让我相信你应该这样做:

    using(ZipFile zipFile = ZipFile.Read(zipPath))
    foreach (ZipEntry entry in zipFile)
    {
      if (entry.FileName == "myXML.xml")
      { 
        XmlDocument xDoc = new XmlDocument();
        //creating the stream and loading the xml doc from the zip file:
        using(Stream stream = zipFile[entry.FileName].OpenReader())
        using(XmlReader xReader = XmlReader.Create(stream))
        {    
            xDoc.Load(xReader);
        }
        //changing the inner text of the doc nodes:
        xDoc.DocumentElement.SelectSingleNode("Account/Name").InnerText = "VeXe";
        xDoc.DocumentElement.SelectSingleNode("Account/Money").InnerText = "Million$";
    
        using(var ms=new MemoryStream())
        using(var sw=new StreamWriter(ms))
        {
            xDoc.Save(sw);
            sw.Flush();
            ms.Position=0;
            zipFile.UpdateEntry(entry.FileName,ms);
        }
        break;
      }
    }
    

    【讨论】:

    • 那是纯粹的迂腐@JohnSaunders。它是 OPs 代码的逐字副本,除了保存部分。您加倍努力,找到文档,编写一些代码并获得迂腐奖励。我会修复它,只为你。 x
    • ...还有一个你没抓到的。
    • @spender 我认为 UpdateItem 只有 2 个重载,其中一个采用一个字符串“itemName”,另一个采用 2 个字符串,“itmeName”和“directoryPathInArchive”。所以没有需要内存流的重载。这就是为什么我得到一个错误。
    • @VeXe :抱歉,本意是使用UpdateEntry(根据链接的文档页面)
    • @spender: 真的没用,zip 中的 xml 没有改变.. 虽然在调试时我看到 xDoc 的节点内部文本的内容正是我的值分配给他们。所以我认为你添加的代码 sn-p 存在某种问题..
    猜你喜欢
    • 2013-07-08
    • 1970-01-01
    • 2017-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多