4

我正在从 API 中提取 1M+ 条记录。拉动工作正常,但是在尝试ReadToEnd进入字符串变量时出现内存不足异常。

这是代码:

        XDocument xmlDoc = new XDocument();

        HttpWebRequest client = (HttpWebRequest)WebRequest.Create(uri);
        client.Timeout = 2100000;//35 minutes
        WebResponse apiResponse = client.GetResponse();

        Stream receivedStream = apiResponse.GetResponseStream();
        StreamReader reader = new StreamReader(receivedStream);

        string s = reader.ReadToEnd();

堆栈跟踪:

at System.Text.StringBuilder.ToString()
at System.IO.StreamReader.ReadToEnd()
at MyApplication.DataBuilder.getDataFromAPICall(String uri) in
    c:\Users\RDESLONDE\Documents\Projects\MyApplication\MyApplication\DataBuilder.cs:line 578
at MyApplication.DataBuilder.GetDataFromAPIAsXDoc(String uri) in
c:\Users\RDESLONDE\Documents\Projects\MyApplication\MyApplication\DataBuilder.cs:line 543

我能做些什么来解决这个问题?

4

4 回答 4

6

听起来您的文件对于您的环境来说太大了。为大文件加载 DOM 可能会出现问题,尤其是在使用 win32 平台时(您尚未说明是否是这种情况)。

您可以将 XmlReader 的速度和内存效率与 XElement/Xnode 等的便利性结合起来,并使用 XStreamingElement 来保存处理后的转换内容。这对于大文件来说内存效率更高

下面是一个伪代码示例:

    // use a XStreamingElement for writing
    var st = new XStreamingElement("root"); 
    using(var xr = new XmlTextReader(stream))
    {
        while (xr.Read())
        {
            // whatever you're interested in
            if (xr.NodeType == XmlNodeType.Element) 
            {
                var node = XNode.ReadFrom(xr) as XElement;
                if (node != null)
                {
                    ProcessNode(node);
                    st.Add(node);
                }
            }

        }
    }
    st.Save(outstream); // or st.WriteTo(xmlwriter);
于 2012-12-04T20:10:59.923 回答
2

当内存是一个问题时, XMLReader是要走的路。它也是最快的。

于 2012-12-05T23:18:51.650 回答
1

不幸的是,您没有显示您的代码,但听起来整个文件正在加载到内存中。这就是你需要避免的。

如果您可以使用流来处理文件而不将整个内容加载到内存中,则最好。

于 2012-12-04T19:24:38.717 回答
0
class MyXmlDocument : IDisposable
    {

        private bool _disposed = false;
        private XmlDocument _xmldoc;

        public XmlDocument xmldoc
        {
            get { return _xmldoc; }
            

        }
        public MyXmlDocument()
        {

            _xmldoc = new XmlDocument();

        }

        ~MyXmlDocument()
        {
            this.Dispose();
        }

        // Public implementation of Dispose pattern callable by consumers.
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        
        }

        // Protected implementation of Dispose pattern.
        protected virtual void Dispose(bool disposing)
        {
            if (_disposed)
            {
                return;
            }

            if (disposing)
            {
                // TODO: dispose managed state (managed objects).
                this._xmldoc = null;
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }

            // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
            // TODO: set large fields to null.

            _disposed = true;
        }

    }

您可以使用它,然后您可以编写如下代码

Using(MyXmlDocument doc = new MyXmlDocument())
{
  doc.xmldoc = xmldoc.Load(new StreamReader(file));
  
}
于 2021-02-22T07:14:45.847 回答