3

この便利な関数を使用して xml ドキュメントを「美しく」し、インデントと改行でフォーマットしました。しかし、より大きなドキュメント (~1MB) では、何らかの理由で doc.Save(writer) で OutOfMemoryException が発生します。この問題を解決するにはどうすればよいですか?

public static string BeautifyXmlDocument(XmlDocument doc)
{
    MemoryStream sb = new MemoryStream();
    XmlWriterSettings s = new XmlWriterSettings();
    s.Indent = true;
    s.IndentChars = "  ";
    s.NewLineChars = "\r\n";
    s.NewLineHandling = NewLineHandling.Replace;
    s.Encoding = new UTF8Encoding(false);
    XmlWriter writer = XmlWriter.Create(sb, s);
    doc.Save(writer);
    writer.Close();
    return Encoding.UTF8.GetString(sb.ToArray());
}

スタックトレース:

at System.IO.MemoryStream.set_Capacity(Int32 value)
at System.IO.MemoryStream.EnsureCapacity(Int32 value)
at System.IO.MemoryStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.Xml.XmlUtf8RawTextWriter.FlushBuffer()
at System.Xml.XmlUtf8RawTextWriter.RawText(Char* pSrcBegin, Char* pSrcEnd)
at System.Xml.XmlUtf8RawTextWriter.RawText(String s)
at System.Xml.XmlUtf8RawTextWriter.WriteFullEndElement(String prefix, String localName, String ns)
at System.Xml.XmlUtf8RawTextWriterIndent.WriteFullEndElement(String prefix, String localName, String ns)
at System.Xml.XmlWellFormedWriter.WriteFullEndElement()
at System.Xml.XmlElement.WriteTo(XmlWriter w)
at System.Xml.XmlElement.WriteContentTo(XmlWriter w)
at System.Xml.XmlElement.WriteTo(XmlWriter w)
at System.Xml.XmlElement.WriteContentTo(XmlWriter w)
at System.Xml.XmlElement.WriteTo(XmlWriter w)
at System.Xml.XmlElement.WriteContentTo(XmlWriter w)
at System.Xml.XmlElement.WriteTo(XmlWriter w)
at System.Xml.XmlElement.WriteContentTo(XmlWriter w)
at System.Xml.XmlElement.WriteTo(XmlWriter w)
at System.Xml.XmlElement.WriteContentTo(XmlWriter w)
at System.Xml.XmlElement.WriteTo(XmlWriter w)
at System.Xml.XmlDocument.Save(XmlWriter w)
4

2 に答える 2

1

実装でドキュメントの完全な文字列を取得する必要がある限り、誰かがいつでもを作成してXmlDocument、を引き起こすことができますOutOfMemoryException。これを実際Streamに回避するには、オブジェクトの使用に移行する必要があります(たとえば、任意TextWriterの場合)。これにより、ドキュメントのごく一部だけが常に実際にメモリに保存されます。美化された文字列の使い方について詳しく教えていただければ、私や他の誰かが役立つかもしれません。

一方、文字列全体がメモリに存在しないように実装を変更できない場合は、投稿された実装を変更して、を使用し、代わりにStringWriterそれを渡す必要がありXmlWriter.Createます。MemoryStream これにより、メモリにとファイナルstringが同時に存在しないため、少なくともメモリの負荷が軽減されます。

public static string BeautifyXmlDocument(XmlDocument doc)
{
    using (StringWriter sw = new StringWriter())
    {
        XmlWriterSettings s = new XmlWriterSettings();
        s.Indent = true;
        s.IndentChars = "  ";
        s.NewLineChars = "\r\n";
        s.NewLineHandling = NewLineHandling.Replace;
        s.Encoding = new UTF8Encoding(false);
        using (XmlWriter writer = XmlWriter.Create(sw, s))
        {
            doc.Save(writer);
        }
        return sw.ToString();
    }
}
于 2012-11-24T22:12:40.180 に答える
1

ストリームを閉じる前に文字列を返してみてください。「using」ステートメントがここで役立ちます。これは、5MB の xml ファイルでは問題なく動作するようです。

  public static string BeautifyXmlDocument(XmlDocument doc)
        {
            using (MemoryStream sb = new MemoryStream())
            {
                XmlWriterSettings s = new XmlWriterSettings();
                s.Indent = true;
                s.IndentChars = "  ";
                s.NewLineChars = "\r\n";
                s.NewLineHandling = NewLineHandling.Replace;
                s.Encoding = new UTF8Encoding(false);
                using (XmlWriter writer = XmlWriter.Create(sb, s))
                {
                    doc.Save(writer);
                    return Encoding.UTF8.GetString(sb.ToArray());
                }
            }
        }
于 2012-11-24T22:04:16.490 に答える